Skip to content

Conversation

@metamaskbot
Copy link
Collaborator

@metamaskbot metamaskbot commented Nov 17, 2025

🚀 v7.60.0 Testing & Release Quality Process

Hi Team,
As part of our new MetaMask Release Quality Process, here’s a quick overview of the key processes, testing strategies, and milestones to ensure a smooth and high-quality deployment.


📋 Key Processes

Testing Strategy

  • Developer Teams:
    Conduct regression and exploratory testing for your functional areas, including automated and manual tests for critical workflows.
  • QA Team:
    Focus on exploratory testing across the wallet, prioritize high-impact areas, and triage any Sentry errors found during testing.
  • Customer Success Team:
    Validate new functionalities and provide feedback to support release monitoring.

GitHub Signoff

  • Each team must sign off on the Release Candidate (RC) via GitHub by the end of the validation timeline (Tuesday EOD PT).
  • Ensure all tests outlined in the Testing Plan are executed, and any identified issues are addressed.

Issue Resolution

  • Resolve all Release Blockers (Sev0 and Sev1) by Tuesday EOD PT.
  • For unresolved blockers, PRs may be reverted, or feature flags disabled to maintain release quality and timelines.

Cherry-Picking Criteria

  • Only critical fixes meeting outlined criteria will be cherry-picked.
  • Developers must ensure these fixes are thoroughly reviewed, tested, and merged by Tuesday EOD PT.

🗓️ Timeline and Milestones

  1. Today (Friday): Begin Release Candidate validation.
  2. Tuesday EOD PT: Finalize RC with all fixes and cherry-picks.
  3. Wednesday: Buffer day for final checks.
  4. Thursday: Submit release to app stores and begin rollout to 1% of users.
  5. Monday: Scale deployment to 10%.
  6. Tuesday: Full rollout to 100%.

✅ Signoff Checklist

Each team is responsible for signing off via GitHub. Use the checkbox below to track signoff completion:

Team sign-off checklist

  • Accounts Framework
  • Assets
  • Card
  • Confirmations
  • Core Platform
  • Design System
  • Earn
  • Mobile Platform
  • Mobile UX
  • Network Enablement
  • New Networks
  • Onboarding
  • Perps
  • Predict
  • Ramp
  • Rewards
  • Swaps and Bridge
  • Transactions
  • Wallet Integrations

This process is a major step forward in ensuring release stability and quality. Let’s stay aligned and make this release a success! 🚀

Feel free to reach out if you have questions or need clarification.

Many thanks in advance

Reference

vinnyhoward and others added 30 commits November 11, 2025 20:18
## **Description**

The header and header icons aren't aligned

## **Changelog**

CHANGELOG entry:null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-196

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

`~`

### **Before**

<img width="500" alt="before"
src="https://github.com/user-attachments/assets/d158d2cf-8f31-44a6-aba2-1823cc3f5669"
/>

### **After**

<img width="500" alt="after"
src="https://github.com/user-attachments/assets/62f27aa9-9b41-44ce-bf80-2367a2b1bedc"
/>

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Vertically centers the Wallet header content and sets a fixed 72px
header height, updating snapshots accordingly.
> 
> - **UI (Navbar)**:
> - Add `innerStyles.headerContainer` in
`app/components/UI/Navbar/index.js` with `height: 72` and `alignItems:
'center'`.
> - Apply `style={innerStyles.headerContainer}` to `HeaderBase` in
`getWalletNavbarOptions` to enforce alignment and height.
> - **Tests**:
> - Update Wallet view snapshots to reflect centered header and fixed
height (`__snapshots__/index.test.tsx.snap`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
32279d4. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR implements optimistic updates for Predict positions to provide
immediate user feedback when placing BUY/SELL orders, significantly
improving the user experience by showing skeleton loaders instead of
stale data while waiting for API confirmation.

### What is the reason for the change?

Previously, when users placed orders in the Predict feature, they had to
wait for the API to confirm the transaction before seeing their position
update. This created a poor UX where:

1. Users saw outdated position values after placing orders
2. No visual feedback indicated that an order was processing
3. Users were unsure if their action succeeded until API confirmed

### What is the improvement/solution?

**Implemented a comprehensive optimistic updates system:**

#### Core Features

- **Optimistic position creation**: When users BUY, create an immediate
optimistic position with expected values
- **Optimistic position updates**: When users BUY more of an existing
position, optimistically update with accumulated values
- **Optimistic position removal**: When users SELL or CLAIM, immediately
hide the position from the list
- **Smart validation**: Compare API responses with expected sizes to
know when to remove optimistic updates
- **Auto-cleanup**: Remove optimistic updates after 1-minute timeout if
API never confirms
- **Defensive checks**: Prevent optimistic updates on claimable
positions

#### Implementation Details

1. **PolymarketProvider.ts** (~450 lines added):
   - Added `OptimisticUpdateType` enum (CREATE, UPDATE, REMOVE)
- Added `OptimisticPositionUpdate` interface with type, position data,
and expected size
- Added `#optimisticPositionUpdatesByAddress` Map to track updates per
user address
   - Implemented `createOrUpdateOptimisticPosition()` for BUY orders
   - Implemented `removeOptimisticPosition()` for SELL/CLAIM orders
- Implemented `applyOptimisticPositionUpdates()` to merge optimistic
data with API responses
- Implemented `isApiPositionUpdated()` with 0.1% tolerance for size
validation
- Added cleanup logic for expired optimistic updates (1-minute timeout)

2. **UI Components**:
- **PredictPosition.tsx**: Added skeleton loaders for current value and
PnL when `optimistic: true`
- **PredictPositionDetail.tsx**: Added skeleton loaders and disabled
"Cash out" button for optimistic positions
- **PredictPosition types**: Added `optimistic?: boolean` flag to
`PredictPosition` type

3. **Controller**:
- **PredictController.ts**: Include fees in optimistic balance
calculation for accurate display

4. **Comprehensive Test Coverage** (~1,830 lines of tests):
   - Fixed 8 failing tests from system migration
- Added 21 new tests covering CREATE, UPDATE, REMOVE, integration, and
UI scenarios
   - Achieved 91.53% statement coverage and 91.75% line coverage

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
[PRED-294](https://consensyssoftware.atlassian.net/browse/PRED-294)

## **Manual testing steps**

```gherkin
Feature: Optimistic updates for Predict positions

  Scenario: User buys a new position
    Given user is on the Predict Positions screen
    And user has no position in a market

    When user places a BUY order for a position
    Then user immediately sees the new position in their list
    And the position shows skeleton loaders for value and PnL
    And the initial value and shares are displayed

    When the API confirms the order (within 1 minute)
    Then the skeleton loaders are replaced with actual values
    And the position shows real-time current value and PnL

  Scenario: User sells an existing position
    Given user is on the Predict Positions screen
    And user has an existing position

    When user places a SELL order for the position
    Then the position immediately disappears from the list

    When the API confirms the sale
    Then the position remains hidden (optimistic update removed)

  Scenario: User buys more of an existing position
    Given user has an existing position with 10 shares

    When user places another BUY order for the same position
    Then the position shows skeleton loaders
    And the expected accumulated values are displayed

    When the API confirms the order
    Then actual updated values replace the skeletons

  Scenario: API timeout cleanup
    Given user placed a BUY order 1 minute ago
    And the API has not yet confirmed

    When 1 minute has passed since the order
    Then the optimistic update is automatically cleaned up
    And user sees either the confirmed API position or no position
```

## **Screenshots/Recordings**

### **Before**

After placing an order, users saw stale position data with no indication
that an order was processing.

### **After**

After placing an order, users immediately see:

- New positions appear with skeleton loaders
- Existing positions update with skeleton loaders
- Sold positions disappear immediately
- Skeleton loaders are replaced with real values when API confirms


https://github.com/user-attachments/assets/a2b08c94-f223-41a0-b85f-615abd800780

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---

## **Technical Implementation Summary**

### Files Changed

- `PolymarketProvider.ts`: +450 lines (optimistic update system)
- `PredictPosition.tsx`: +29 lines (skeleton loaders)
- `PredictPositionDetail.tsx`: +27 lines (skeleton loaders, disabled
button)
- `PredictController.ts`: +3 lines (fee calculation)
- `types/index.ts`: +1 line (`optimistic?: boolean` flag)
- Test files: +1,830 lines (comprehensive coverage)

### Optimistic Update Flow

**BUY Order:**

1. User places BUY order → `placeOrder()` called
2. Order submitted to API via `submitClobOrder()`
3. On success, `createOrUpdateOptimisticPosition()` called
4. Optimistic position created with `optimistic: true` flag
5. `getPositions()` merges optimistic position with API data
6. UI shows skeleton loaders for value/PnL
7. When API returns position with expected size → optimistic update
removed
8. If API doesn't confirm within 1 minute → optimistic update expires

**SELL/CLAIM Order:**

1. User places SELL/CLAIM order → `placeOrder()` or `confirmClaim()`
called
2. `removeOptimisticPosition()` marks position for removal
3. `getPositions()` filters out the position
4. Position immediately disappears from UI
5. When API confirms (position gone or size reduced) → optimistic update
removed

### Test Coverage

**Total: 21 new tests added**

**PolymarketProvider (14 tests):**

- CREATE scenarios: 7 tests (position creation, value calculation,
market details)
- UPDATE scenarios: 4 tests (accumulation, avgPrice, preservation)
- Integration: 3 tests (BUY→confirm, timeout, BUY→SELL)

**UI Components (7 tests):**

- PredictPosition: 4 tests (skeleton display, value hiding)
- PredictPositionDetail: 3 tests (skeleton display, button state)

**Coverage Achieved:**

- Statements: 91.53% ✅
- Branches: 83.01% ✅
- Functions: 91.6% ✅
- Lines: 91.75% ✅

All metrics exceed the 80% target.

[PRED-294]:
https://consensyssoftware.atlassian.net/browse/PRED-294?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds full optimistic position create/update/remove flow with UI
skeletons, disables actions during optimism, adjusts balance for fees,
and expands tests.
> 
> - **Predict Provider (Polymarket)**:
> - Implement optimistic updates system (`CREATE`/`UPDATE`/`REMOVE`) via
in-memory map keyed by address and `outcomeTokenId`.
> - Merge optimistic state in `getPositions` with timeout cleanup (1
min) and API-size validation tolerance.
> - Block orders on claimable positions; add targeted fetch by
`outcomeId` in `getPositions`.
> - Apply optimistic removal on SELL and CLAIM; create/update optimistic
positions on BUY using market details when available.
> - **UI**:
> - `PredictPosition` and `PredictPositionDetail`: show skeletons for
value/PnL when `position.optimistic` is true; disable "Cash out" for
optimistic positions.
> - **Controller**:
> - Deduct total fees from balance during optimistic BUY balance update.
> - **Types/Providers API**:
> - Add `optimistic?: boolean` to `PredictPosition`; add `outcomeId` to
`GetPositionsParams` and wire through provider method.
> - **Tests**:
> - Extensive new tests covering optimistic create/update/remove flows,
integration scenarios, and UI behavior.
> - **Misc**:
>   - Minor hook lint suppression in `usePredictPrices`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
144511a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR reverts commit 74b8745 from PR
#21199.

**What is the reason for the change?**
The font preloader changes introduced in #21199 are causing rendering
bugs in the application:
- Text is being cut off in various components
- Font weights are not loading correctly
- The comprehensive font preloading approach is causing unexpected
layout issues

**What is the improvement/solution?**
This revert restores the previous variant-based font preloading
approach, which:
- Preloads only the specific TextVariant fonts that are actively used
- Maintains stable font rendering without text cutoff issues
- Ensures font weights load properly across all components
- Restores the working implementation until the font loading issues can
be properly addressed

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: #22301
Reverts: #21199
Original commit: 74b8745

## **Manual testing steps**

```gherkin
Feature: Font rendering after revert

  Scenario: user views text content across the app
    Given the user has the app running with the reverted font preloader
    And the user navigates through different screens with various text components

    When the user views text content in input fields, headings, and body text
    Then all text should be fully visible without cutoff
    And font weights should render correctly (regular, medium, bold)
    And there should be no layout shifting or text overflow issues
```

## **Screenshots/Recordings**

### **Before**
N/A - This is a revert PR

### **After**
N/A - This is a revert PR

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Reverts/rewrites font preloader to load only TextVariant fonts and
updates input styles to set fontWeight from theme while removing
hardcoded lineHeight/fontFamily; updates tests and snapshots
accordingly.
> 
> - **Fonts**:
> - **Preloader** (`app/core/FontPreloader/FontPreloader.ts`): revert to
variant-based font loading using `TextVariant` and `getFontFamily`;
preload 400/500/700 weights on web; streamline native preload and
logging.
> - **Tests**
(`app/core/FontPreloader/__tests__/FontPreloader.test.ts`): simplify and
align with new preloader behavior (singleton, RN preload, concurrency,
reset, errors, promise access).
> - **UI Styles**:
> - **Inputs** (`app/component-library/.../Input.styles.ts`): apply
`fontWeight` from `theme.typography[textVariant]`; keep baseline
alignment; minor comment/format tweak.
> - Remove hardcoded `fontFamily` in custom inputs
(`Views/EnterPasswordSimple/index.js`,
`Views/RevealPrivateCredential/styles.ts`,
`Views/MultichainAccounts/PrivateKeyList/styles.ts`).
> - **Snapshots**: update across UI to reflect `fontWeight: "400"` and
removal of explicit `lineHeight`/`fontFamily` where applicable.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
09ccad9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR implements automatic eligibility refresh for the Predict feature
when the app comes to foreground. Previously, eligibility was only
checked on initial load or manual refresh. Now, when a user backgrounds
the app and then returns to it, the eligibility status is automatically
refreshed.

**What is the reason for the change?**
Users may change their network configuration (e.g., switching between
different network connections) while the app is backgrounded. When they
return to the app, the Predict feature should automatically check
eligibility again to reflect any potential changes in their connection
status.

**What is the improvement/solution?**

- Added an `AppState` listener to the `usePredictEligibility` hook that
detects when the app transitions from `background`/`inactive` to
`active` state
- Implemented 1-minute debouncing to prevent excessive API calls if the
user switches in and out of the app multiple times
- Manual refresh functionality remains unchanged and bypasses the
debounce
- Added comprehensive error handling and logging

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: N/A

## **Manual testing steps**

```gherkin
Feature: Auto-refresh Predict eligibility on app focus

  Scenario: user returns to app and eligibility is refreshed
    Given user has opened the Predict feature
    And user is eligible to use Predict

    When user backgrounds the app (switches to another app)
    And user returns to the app
    Then eligibility is automatically refreshed
    And user sees updated eligibility status if it changed

  Scenario: user rapidly switches in and out of app
    Given user has opened the Predict feature
    And eligibility was just refreshed

    When user backgrounds the app
    And user returns to the app within 1 minute
    Then eligibility refresh is skipped due to debouncing
    And user still has access to Predict feature

  Scenario: user returns after debounce period
    Given user has opened the Predict feature
    And eligibility was refreshed more than 1 minute ago

    When user backgrounds the app
    And user returns to the app
    Then eligibility is automatically refreshed
```

## **Screenshots/Recordings**

N/A - This is an internal behavior change with no visual UI impact.

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduce a singleton-managed AppState listener to auto-refresh
Predict eligibility on app foreground with 1-minute debounce, logging,
and race-condition prevention, plus comprehensive tests.
> 
> - **Predict Hook (`usePredictEligibility.ts`)**:
>   - **Singleton manager (`EligibilityRefreshManager`)**:
> - Manages a single `AppState` `change` listener across hook instances.
> - Refreshes `Engine.context.PredictController.refreshEligibility()` on
transition to `active`.
> - Debounces auto-refreshes by 60s; manual `refreshEligibility`
bypasses debounce.
> - Prevents concurrent calls by reusing in-flight promise; tracks last
refresh time.
> - Registers/unregisters per hook mount/unmount; adds detailed
`DevLogger` logs and error handling.
> - **Tests (`usePredictEligibility.test.ts`)**:
> - Cover eligibility state selection, singleton
registration/unregistration, app focus auto-refresh, debounce behavior,
manual refresh bypass, error logging/continuation, and
concurrency/race-condition scenarios.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8c94340. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

This PR migrates the Predict feature flag from a simple boolean flag to
a version-gated feature flag structure, aligning it with the pattern
used by Perps and other features.

**What is the reason for the change?**
The Predict feature needs version gating to ensure users have the
minimum required app version (7.60.0) before accessing the feature. The
previous implementation used a simple boolean flag (`predictEnabled`)
which didn't support version checking.

**What is the improvement/solution?**

- Changed flag name from `predictEnabled` to `predictTradingEnabled` to
follow naming conventions
- Implemented version-gated structure with `enabled` and
`minimumVersion` properties
- Added environment variable fallback (`MM_PREDICT_ENABLED`) for local
development
- Updated all references across the codebase (selectors, tests, mocks,
E2E helpers)
- Ensured backward compatibility by maintaining the same boolean return
type

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: Predict feature flag version gating

  Scenario: user with app version below minimum cannot access Predict
    Given user has app version 7.59.0
    And remote feature flag predictTradingEnabled is enabled with minimumVersion "7.60.0"

    When user navigates to Wallet screen
    Then Predict feature should not be visible/accessible

  Scenario: user with app version at or above minimum can access Predict
    Given user has app version 7.60.0 or higher
    And remote feature flag predictTradingEnabled is enabled with minimumVersion "7.60.0"

    When user navigates to Wallet screen
    Then Predict feature should be visible and accessible

  Scenario: local environment variable overrides when remote flag unavailable
    Given remote feature flags are empty or invalid
    And MM_PREDICT_ENABLED environment variable is set to "true"

    When app initializes
    Then Predict feature should be enabled based on local flag

  Scenario: remote flag takes precedence over local flag
    Given remote feature flag predictTradingEnabled is explicitly disabled
    And MM_PREDICT_ENABLED environment variable is set to "true"

    When app initializes
    Then Predict feature should be disabled (remote flag overrides local)
```

## **Screenshots/Recordings**

Not applicable - This is an internal refactoring with no UI changes.

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---

## **Technical Details**

### Files Modified (7 total)

1. **`app/components/UI/Predict/selectors/featureFlags/index.ts`**
   - Migrated from boolean flag to `VersionGatedFeatureFlag` structure
   - Changed flag name: `predictEnabled` → `predictTradingEnabled`
   - Added environment variable fallback: `MM_PREDICT_ENABLED`
   - Added comprehensive JSDoc documentation

2. **`app/components/UI/Predict/selectors/featureFlags/index.test.ts`**
   - Rewrote tests following unit testing guidelines (AAA pattern)
   - Added comprehensive test coverage for version gating
   - Added tests for remote flag precedence over local flags
   - Added tests for invalid flag scenarios
   - All 19 tests passing ✅

3. **`app/components/UI/Predict/mocks/remoteFeatureFlagMocks.ts`**
   - Updated mock structure to version-gated format

4. **`app/components/Views/Wallet/index.test.tsx`**
   - Updated 5 occurrences of `predictEnabled` → `predictTradingEnabled`

5. **`.js.env.example`**
   - Added `MM_PREDICT_ENABLED` environment variable example

6. **`e2e/api-mocking/helpers/remoteFeatureFlagsHelper.ts`**
   - Updated default mock to version-gated structure

7. **`e2e/api-mocking/mock-responses/feature-flags-mocks.ts`**
   - Updated `remoteFeatureFlagPredictEnabled` function

### Key Implementation Details

- **Flag Structure**: `{ enabled: boolean, minimumVersion: string }`
- **Backend Flag Name**: `predictTradingEnabled`
- **Minimum Version**: `7.60.0`
- **Local Fallback**: `MM_PREDICT_ENABLED` environment variable
(defaults to `false`)
- **Validation**: Uses `validatedVersionGatedFeatureFlag()` utility for
type checking and version validation

### Test Coverage

- ✅ Remote flag precedence over local flags
- ✅ Version gating validation
- ✅ Invalid flag type handling
- ✅ Fallback to local environment variable
- ✅ Edge cases (null, undefined, empty objects)

### Breaking Changes

None - The selector maintains the same boolean return type, ensuring
backward compatibility with existing code.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Migrates Predict flag to version-gated `predictTradingEnabled` (with
minimumVersion and `MM_PREDICT_ENABLED` fallback) and updates selectors,
tests, and mocks accordingly.
> 
> - **Predict feature flag**:
>   - Rename `predictEnabled` → `predictTradingEnabled`.
> - Adopt version-gated structure `{ enabled, minimumVersion }` (min app
`7.60.0`).
> - Update selector to validate remote flag and fallback to
`MM_PREDICT_ENABLED`.
> - **Tests**:
> - Add/expand unit tests for precedence, version gating, and invalid
scenarios in `selectors/featureFlags`.
>   - Update `Wallet` tests to use `predictTradingEnabled` objects.
> - **Mocks/E2E**:
>   - Update Predict mocks and remote flags helpers to new structure.
>   - Add `MM_PREDICT_ENABLED` to `.js.env.example`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8997c9e. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
#22499)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Changes the auto-refresh behavior in usePredictOrderPreview from
interval-based
to sequential pattern. The timer now waits for the preview response
before
starting the timeout countdown, preventing overlapping requests.

Key changes:
- Replace setInterval with recursive setTimeout pattern
- Add scheduleNextRefresh function to trigger after response
- Schedule next refresh after both successful and error responses
- Clear pending timers on unmount and parameter changes
- Update tests to verify sequential refresh behavior

This ensures the autoRefreshTimeout is a delay AFTER each response
completes, rather than a fixed interval that could cause overlapping
requests when API response times exceed the timeout value.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:
[PRED-299](https://consensyssoftware.atlassian.net/browse/PRED-299?atlOrigin=eyJpIjoiOTQwNThkMTg4N2UzNDQ1MjljZTEyNGM0MTlhOGZjMjUiLCJwIjoiaiJ9)

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Replaces interval-based auto-refresh with response-triggered
sequential timeouts in `usePredictOrderPreview`, adds cleanup on param
changes/unmount, and updates tests accordingly.
> 
> - **Hook `usePredictOrderPreview`**:
> - Replace `setInterval` auto-refresh with sequential `setTimeout`
scheduled via `scheduleNextRefresh` after each response (success or
error).
> - Introduce refs for timer and callbacks: `refreshTimerRef`,
`calculatePreviewRef`, `scheduleNextRefreshRef`.
> - Clear pending refresh timers on unmount and when parameters change;
debounce initial calculation.
> - Minor safety: optional chaining on
`calculatePreviewRef.current?.()`.
> - **Tests `usePredictOrderPreview.test.ts`**:
> - Rename and add cases to verify response-triggered scheduling,
waiting before countdown, scheduling after errors, and clearing timers
on parameter changes and unmount.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2c9fb28. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

[PRED-299]:
https://consensyssoftware.atlassian.net/browse/PRED-299?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR bumps the network-enablement-controller to version 3.1.0 that
includes monad in the constant.
This allows monad to be selected when clicking on the `All popular
networks` button in the Networks Modal.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: bumps network-enablement-controller and apply patch
similar to patch on 3.0.0

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->
<img width="384" height="792" alt="Screenshot 2025-11-11 at 17 01 05"
src="https://github.com/user-attachments/assets/0726e0c3-eb8a-4817-9e4a-f101a664274b"
/>



### **After**

<!-- [screenshots/recordings] -->

<img width="384" height="792" alt="Screenshot 2025-11-11 at 17 11 43"
src="https://github.com/user-attachments/assets/83bc4ca7-adf1-42ef-be11-3db8842deef0"
/>


## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Updates @metamask/network-enablement-controller to 3.1.0 with a patch
that enables additional EVM networks by default.
> 
> - **Dependencies**:
> - Bump `@metamask/network-enablement-controller` from `3.0.0` to
`3.1.0` using a Yarn patch.
> - **Network defaults** (`dist/NetworkEnablementController.cjs`):
> - Extend default-enabled EVM networks by adding `ArbitrumOne`,
`BscMainnet`, `OptimismMainnet`, `PolygonMainnet`, and `SeiMainnet`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b41bb09. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…21990)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->


When Redux state migrations fail, redux-persist resets the state to
defaults and updates the version number to the latest, preventing
migrations from re-running. This leaves users stuck on the onboarding
screen unable to access their wallets, even though their vault backup
exists in secure storage.

## Implementation

### 1. Vault Recovery Detection on Onboarding Screen

Added automatic detection when users land on the onboarding screen with
an existing vault backup:
- Detects migration failure scenario: `!existingUser` (Redux reset) +
vault backup exists
- Skips detection if user explicitly deleted their wallet
(`route.params.delete`)
- Automatically navigates to vault recovery screen
- Users can restore their wallet using their password
- Prevents data loss from failed migrations

**Files Changed:**
- `app/components/Views/Onboarding/index.js` - Added vault recovery
detection
- `app/components/Views/RestoreWallet/WalletRestored.tsx` - Sets
`existingUser` flag after restore

### 2. Fixed Vault Recovery Persistence Bug

Fixed critical bug where vault recovery didn't persist controller state
changes:
- Added `setupEnginePersistence()` call in `initializeVaultFromBackup()`
path
- Ensures controller state changes are saved to individual files after
vault recovery
- Previously caused infinite vault recovery loops after successful
restore
- Consolidated persistence setup in `initializeControllers()` for
consistency

**Files Changed:**
- `app/core/EngineService/EngineService.ts` - Fixed persistence setup in
vault recovery path

### 3. Fixed Race Condition in Wallet Deletion

Prevents temporary wallets (created during reset) from being backed up:
- Added `disableAutomaticVaultBackup` flag to temporarily disable vault
backups during wallet reset
- Clears all vault backups before creating temporary wallet
- Re-enables automatic backups in `finally` block for robustness
- Applies to both manual wallet deletion and OAuth error recovery
- Prevents false vault recovery prompts after intentional wallet resets

**Files Changed:**
- `app/core/Engine/Engine.ts` - Added circuit breaker flag
- `app/components/hooks/DeleteWallet/useDeleteWallet.ts` - Manual
deletion fix
- `app/core/Authentication/Authentication.ts` - Uncommented
`setExistingUser(true)` for new wallets
- `app/core/BackupVault/backupVault.ts` - Vault backup utilities

### 4. Fixed Migration Inflation/Deflation Logic

Corrected conditions for the new file-based persistence system
(migrations 104-105):
- **Inflation**: `> 106` - Only migrations 106+ need to inflate from
individual controller files
- **Deflation**: `>= 106` - Migration 106 is the first to deflate into
individual controller files
- Only future migrations require inflation, that will follow this PR
- Ensures smooth transition to new persistence system without breaking
app on restart

**Files Changed:**
- `app/store/migrations/index.ts` - Fixed inflation/deflation conditions
and removed debug logs
- `app/store/migrations/index.test.ts` - Updated tests to reflect
correct logic

### 5. Code Cleanup

Removed all debugging logs added during investigation:
- `app/components/Views/Onboarding/index.js` - Removed migration
detection logs
- `app/core/EngineService/EngineService.ts` - Removed persistence setup
logs
- `app/store/migrations/index.ts` - Removed KeyringController debug logs
- `app/core/BackupVault/backupVault.ts` - Simplified error handling
- `app/core/Engine/Engine.ts` - Removed vault backup logs

### 6. Test Compliance

Fixed unit test naming violations to comply with project guidelines:
- Updated 19 tests in `EngineService.test.ts` to remove "should" from
test names
- Ensured all tests follow action-oriented naming convention

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

**Feature: Vault Recovery After Migration Failure**

  Scenario: user restores wallet after migration failure
    Given user has MetaMask installed with wallet data
    And a state migration fails during app startup
    And redux state is reset to defaults
    And vault backup exists in secure storage

    When user opens the app
    Then user sees the vault recovery screen automatically
    
    When user enters their wallet password
    Then user successfully restores their wallet
    And user can access their accounts and assets


**Feature: Manual Wallet Deletion**

  Scenario: user deletes wallet without false vault recovery
    Given user has MetaMask installed with an active wallet
    And user is on the Settings screen

    When user navigates to "Security & Privacy"
    And user taps "Delete Wallet"
    And user confirms the deletion
    And user restarts the app
    Then user sees the onboarding screen
    And user does NOT see the vault recovery screen


**Feature: OAuth Login Error Recovery**

  Feature: Vault Recovery After Migration Failure

  Scenario: user restores wallet after migration failure
    Given user has MetaMask installed with wallet data
    And a state migration fails during app startup
    And redux state is reset to defaults
    And vault backup exists in secure storage

    When user opens the app
    Then user sees the vault recovery screen automatically
    
    When user enters their wallet password
    Then user successfully restores their wallet
    And user can access their accounts and assets


**Feature: Manual Wallet Deletion**

  Scenario: user deletes wallet without false vault recovery
    Given user has MetaMask installed with an active wallet
    And user is on the Settings screen

    When user navigates to "Security & Privacy"
    And user taps "Delete Wallet"
    And user confirms the deletion
    And user restarts the app
    Then user sees the onboarding screen
    And user does NOT see the vault recovery screen


**Feature: OAuth Login Error Recovery**

Scenario: user experiences OAuth backup failure without false vault
recovery
    Given user is creating a new wallet with OAuth (Google/Apple login)
    And local wallet creation succeeds
    And cloud backup fails during OAuth process

    When the error handler resets the wallet state
    And user restarts the app
    Then user sees the onboarding screen
    And user does NOT see the vault recovery screen
    And user can retry OAuth login or import with seed phrase


**Feature: Migration System Upgrade Path**

  Scenario: user upgrades from version 103 to version 104+
    Given user has MetaMask version with migrations up to 103
    And controller data is stored in redux-persist
    And user has an active wallet

    When user upgrades to version 104 or higher
    Then migrations 104+ run successfully
    And controller data is deflated to individual files
    And user's wallet remains accessible
    And app functions normally after restart


  Scenario: user upgrades from version 104 to version 105+
    Given user has MetaMask version 104
    And controller data is in individual files
    And user has an active wallet

    When user upgrades to version 105 or higher
    Then controller data is inflated for migrations
    And new migrations run successfully
    And controller data is deflated back to individual files
    And user's wallet remains accessible
And app functions normally after restart**: user experiences OAuth
backup failure without false vault recovery
    Given user is creating a new wallet with OAuth (Google/Apple login)
    And local wallet creation succeeds
    And cloud backup fails during OAuth process

    When the error handler resets the wallet state
    And user restarts the app
    Then user sees the onboarding screen
    And user does NOT see the vault recovery screen
    And user can retry OAuth login or import with seed phrase


**Feature: Migration System Upgrade Path**

  Scenario: user upgrades from version 103 to version 104+
    Given user has MetaMask version with migrations up to 103
    And controller data is stored in redux-persist
    And user has an active wallet

    When user upgrades to version 104 or higher
    Then migrations 104+ run successfully
    And controller data is deflated to individual files
    And user's wallet remains accessible
    And app functions normally after restart


  Scenario: user upgrades from version 104 to version 105+
    Given user has MetaMask version 104
    And controller data is in individual files
    And user has an active wallet

    When user upgrades to version 105 or higher
    Then controller data is inflated for migrations
    And new migrations run successfully
    And controller data is deflated back to individual files
    And user's wallet remains accessible
    And app functions normally after restart

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Detects migration failure and routes to vault recovery, ensures
controller persistence after recovery, prevents backing up temporary
wallets during resets, and updates login/recovery flows with tests.
> 
> - **Onboarding/Recovery**:
> - Detects migration failure on `Onboarding` by checking vault backup
and `existingUser`; skips in E2E and explicit delete, then navigates to
`Routes.VAULT_RECOVERY.RESTORE_WALLET`.
> - `WalletRestored` now routes to `Routes.ONBOARDING.LOGIN` with
`isVaultRecovery` instead of auto-auth; adds tests.
> - `Login` sets `existingUser` via `setExistingUser(true)` after
successful unlock when `isVaultRecovery` is true; adds tests.
> - **Engine/Authentication**:
> - Adds `Engine.disableAutomaticVaultBackup` and skips `backupVault`
when true.
> - Clears vault backups and temporarily disables auto-backup during
wallet reset and OAuth error recovery; always re-enables.
> - `EngineService` moves filesystem persistence setup to
`initializeControllers` and ensures it runs after vault recovery;
updates batching and tests.
> - **Hooks/Tests**:
> - `useDeleteWallet` clears backups first, disables auto-backup during
reset, re-enables in `finally`, and resets controllers; adds robust
tests.
> - Renames and tightens numerous test titles/expectations; snapshot
names updated.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ed1a8a7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--

Please submit this PR as a draft initially.

Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.

-->

## **Description**

This PR adds analytics tracking for social login failures to help
identify where and why failures occur during the OAuth login flow.

The implementation tracks failures at three stages:
1. **Provider login failures** - When users cancel or encounter errors
during the OAuth provider authentication step
2. **Token exchange failures** - When errors occur during the
authorization code to JWT token exchange
3. **Seedless authentication failures** - When errors occur during the
seedless authentication step

Each failure event includes contextual metadata:
- `account_type` - The type of account being created (e.g.,
`default_google`, `default_apple`)
- `is_rehydration` - Whether this is a rehydration flow (existing user
returning)
- `failure_type` - Whether the failure was due to user cancellation or
an error
- `error_category` - The specific stage where the failure occurred

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/SL-257

## **Manual testing steps**

1. Start a social login flow (Google or Apple)
2. Cancel the OAuth provider authentication dialog
3. Verify that a `SocialLoginFailed` event is tracked with
`failure_type: 'user_cancelled'` and `error_category: 'provider_login'`
4. Attempt a social login and simulate a network error during token
exchange
5. Verify that a `SocialLoginFailed` event is tracked with
`failure_type: 'error'` and `error_category: 'get_auth_tokens'`
6. Attempt a social login and simulate an error during seedless
authentication
7. Verify that a `SocialLoginFailed` event is tracked with
`failure_type: 'error'` and `error_category: 'seedless_auth'`

## **Screenshots/Recordings**

<!-- Not applicable - this is an analytics-only change with no UI
changes -->

### **Before**

<!-- N/A -->

### **After**

<!-- N/A -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds SOCIAL_LOGIN_FAILED tracking with rehydration context across
provider login, token exchange, and seedless auth; updates OAuth login
API and tests accordingly.
> 
> - **Analytics**:
> - Add `SOCIAL_LOGIN_FAILED` event in
`core/Analytics/MetaMetrics.events.ts` and export mapping.
> - **OAuth** (`core/OAuthService/OAuthService.ts`):
> - Add `userClickedRehydration` to local state and
`#trackSocialLoginFailure` to emit `SOCIAL_LOGIN_FAILED` with
`account_type`, `is_rehydration`, `failure_type`, and `error_category`.
> - Invoke tracking on failures in `provider_login`, `get_auth_tokens`,
and `seedless_auth` stages; validate `id_token` earlier.
> - Change `handleOAuthLogin(loginHandler, userClickedRehydration)`
signature and wire usage.
> - **Onboarding** (`components/Views/Onboarding/index.js`):
>   - Pass rehydration flag to `handleOAuthLogin` (`!createWallet`).
> - **Tests**:
> - Update unit tests in `OAuthService.test.ts` and
`Onboarding/index.test.tsx` to reflect new `handleOAuthLogin` param and
event behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
37e8b08. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
This PR fixes styling for "unconfirmed" transaction status
<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Fixed styling for "unconfirmed" transaction status

## **Related issues**

Fixes: #21574
https://consensyssoftware.atlassian.net/browse/TMCU-158

## **Manual testing steps**

```gherkin
Feature: Send BTC

  Scenario: user sends BTC
    Given BTC is enabled

    When user initiates BTC transaction and navigates to Activity tab
    Then unconfirmed transaction with yellow/orange "Pending" status should appear
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**
<img width="395" height="835" alt="Screenshot 2025-11-07 at 13 53 14"
src="https://github.com/user-attachments/assets/e74b1b50-be28-4800-a1cc-6be00665d119"
/>

<!-- [screenshots/recordings] -->

### **After**
<img width="396" height="833" alt="Screenshot 2025-11-07 at 13 52 51"
src="https://github.com/user-attachments/assets/431a522f-0338-4b22-b39a-29d51d03dfca"
/>

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Maps `Unconfirmed` statuses to pending and enables overriding styles
on status text components; updates i18n and snapshots.
> 
> - **UI**:
>   - `app/components/Base/StatusText.js`:
> - `ConfirmedText`, `PendingText`, `FailedText` now accept optional
`style` prop merged with base styles.
> - Treat `"Unconfirmed"/"unconfirmed"` as pending in `StatusText`
switch.
> - **i18n**:
> - `locales/languages/en.json`: add `"transaction.unconfirmed":
"Pending"`.
> - **Tests**:
> - Update `TransactionDetails` snapshots to reflect array-based `style`
merging.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fa44247. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

PR to add trending tokens card. This should be under a feature flag(
selector `selectAssetsTrendingTokensEnabled`)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: No functional changes, this is still under a feature
flag.

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->
<img width="425" height="858" alt="Screenshot 2025-11-11 at 18 09 58"
src="https://github.com/user-attachments/assets/ff394cf2-fbc8-4965-a2d1-e048eb1990ad"
/>



## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces a Trending Tokens UI section integrated into TrendingView
with a shared token logo hook, updates the trending fetch hook to
default to popular networks, and adds comprehensive tests and i18n.
> 
> - **UI (Trending)**:
> - **Trending Tokens Section**: New `TrendingTokensSection` with
`TrendingTokensList`, `TrendingTokenRowItem`, `TrendingTokenLogo`, and
`TrendingTokensSkeleton`, integrated into `TrendingView` (header tweak,
scroll container).
> - **Hooks**:
> - **New**: `useTokenLogo` for shared image loading/error/background
logic; refactors `PerpsTokenLogo` to use it.
> - **Updated**: `useTrendingRequest` now accepts optional `chainIds`,
defaults to popular networks via
`useNetworksByNamespace`/`useNetworksToUse`, sets initial loading to
true, and fixes debounce dependencies.
> - **Utils**:
> - Add formatting helpers `formatCompactUSD` and `formatMarketStats`
for market cap/volume.
> - **Tests**:
> - Add extensive unit tests and snapshots for new components/hooks and
updated trending request behavior.
> - **Localization**:
> - Update `en.json` with `trending.title`, `trending.view_all`, and
`trending.tokens` strings.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
49ddd1a. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Ensure the Predict withdraw confirmation uses the entire balance if the
`Max` button is used.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
[#6156](MetaMask/MetaMask-planning#6156)
#22190

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Ensure Predict withdraw Max uses the full balance converted to USD and
add a fixed 1:1 USD rate for Polygon USDCE.
> 
> - **Confirmations / Amounts**:
> - Convert Predict balance to USD via `tokenFiatRate` for withdraw
calculations and `Max` behavior; default rate falls back to `1`.
> - Refine max-percentage logic when pay token is missing or matches the
first required token.
> - **Token Fiat Rates**:
> - Return fixed `1` rate for `POLYGON_USDCE` on `POLYGON` when currency
is USD (alongside `ARBITRUM_USDC`).
>   - Minor refactor for USD checks and token matches.
> - **Alerts**:
> - Use human Predict balance in `useInsufficientPredictBalanceAlert`
comparison.
> - **Tests**:
> - Update and add tests for USDCE fixed rate and Predict withdraw USD
conversion/max behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f179f68. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Adjusted the funding tooltip copy in the position component to display
position-specific information. Previously, both the position card's
"Funding Cost" and the market statistics "Funding Rate" used the same
generic tooltip explaining funding rates. This change adds a dedicated
tooltip for funding payments that clarifies it represents the cumulative
amount paid/received since the position opened.

**Changes:**
- Added new `funding_payments` tooltip type
- Updated position card to use the new tooltip
- Market statistics continues to use the existing `funding_rate` tooltip

## **Changelog**

CHANGELOG entry: Updated funding tooltip in position component to show
position-specific information

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-1880

## **Manual testing steps**

```gherkin
Feature: Funding payments tooltip in position component

  Scenario: user views funding tooltip in position card
    Given user has an open perp position
    And the position card displays the "Funding" field with an info icon

    When user taps the info icon next to "Funding" in the position card
    Then the tooltip displays title "Funding payments"
    And the tooltip content reads "This is the amount you've paid in funding fees since the position was opened. Funding is paid or received every hour to keep the perp price close to the actual token price."

  Scenario: user views funding rate tooltip in market statistics
    Given user is viewing market statistics for a perp

    When user taps the info icon next to "Funding rate"
    Then the tooltip displays title "Funding rate"
    And the tooltip content describes the general funding rate concept
```

## **Screenshots/Recordings**

### **Before**

Position card showed generic funding rate tooltip (same as market
statistics)

### **After**

Position card shows position-specific funding payments tooltip with
cumulative payment context


https://github.com/user-attachments/assets/65db42a1-68fc-4758-950f-ad1dd79e1030


## **Pre-merge author checklist**

- [x] I've followed MetaMask Contributor Docs and MetaMask Mobile Coding
Standards
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable (N/A - localization change only)
- [x] I've documented my code using JSDoc format if applicable (N/A)
- [x] I've applied the right labels on the PR

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed)
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces a new `funding_payments` tooltip and switches the position
card’s funding info icon to use it, with corresponding registry and
locale updates.
> 
> - **Perps Tooltips**:
> - Add new content key `funding_payments` to `PerpsTooltipContentKey`
and register in `contentRegistry`.
> - **Position Card**:
> - Change funding info icon handler from `funding_rate` to
`funding_payments` in `PerpsPositionCard`.
> - **Localization**:
> - Add `perps.tooltips.funding_payments` strings (title and content) in
`en.json`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2149df2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

This PR enables back native token send. 

As it stated in the previous automated flaky test thread
[here](https://consensys.slack.com/archives/C02U025CVU4/p1762243312142959)
and the
[logs](https://github.com/MetaMask/metamask-mobile/actions/runs/19055429448/job/54425009493),
send native spec was failing. However if you look at the logs - this is
not entirely related as there is a detox crash.

I ran these tests over and over on local but I couldn't encoutner the
issue once, hence we are enabling it back.


https://github.com/user-attachments/assets/042fdb4f-c846-4e7c-92d9-6985798e3de0

**Update 1** 

We still encounter the issues in the CI - Ola [had a look but no
chance](https://consensys.slack.com/archives/C01U65ZUS2E/p1762787121323169?thread_ts=1762776032.589089&cid=C01U65ZUS2E).
Hence we are disabling this `50%` test rest looks good.

**Update 2** 

It appears the issues are because of `%` text. I changed e2e test to
lookup component test ids instead of text and it worked.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes:  #22135

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [X] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [X] I've completed the PR template to the best of my ability
- [X] I’ve included tests if applicable
- [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [X] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.




<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds testIDs to percentage buttons and updates send flow e2e selectors
to target them by ID.
> 
> - **UI**:
> - Add `testID` to percentage buttons in
`app/components/Views/confirmations/components/edit-amount-keyboard/edit-amount-keyboard.tsx`
as `percentage-button-<value>`.
> - **E2E Tests**:
> - Update `e2e/pages/Send/RedesignedSendView.ts` to select `50%` and
`Max` via
`getElementByID('percentage-button-50'|'percentage-button-100')` instead
of text.
> - Keep send native token spec logic the same while interacting with
the new IDs.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
505718b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…tion cp-7.59.0 (#22252)

## **Description**

This PR implements a major refactor of the Perps order handling system
to address precision and validation issues. The changes establish USD as
the primary source of truth for order amounts, replacing the complex
`findOptimalAmount` optimization logic with a simpler, more robust
approach that recalculates position sizes at execution time using fresh
market prices.

### Key Changes

#### 1. Migration from `findOptimalAmount` to USD-as-Source-of-Truth

**Previous Approach:**
- Used `findOptimalAmount` function to find the "optimal" USD amount
that maximized value while maintaining the same position size
- Performed complex calculations with position size increments and
rounding
- Optimized order amounts on every input change (percentage, slider,
keypad, etc.)
- Position size was calculated once in the UI and used directly for
order placement

**New Approach:**
- **USD amount is now the primary source of truth** - stored and
validated as entered by user
- Position size is recalculated at execution time with the freshest
available price
- Eliminates complex optimization logic (~150 lines removed from
`orderCalculations.ts`)
- Simplified order form handling (~71 lines removed from
`usePerpsOrderForm.ts`)

**Benefits:**
- Eliminates edge cases where optimization could produce invalid orders
- Reduces computational overhead on every input change
- More predictable behavior - what user enters is what gets validated
and executed
- Better handling of price volatility during order placement

#### 2. Standardized Slippage Management

**New Configuration:**
```typescript
export const ORDER_SLIPPAGE_CONFIG = {
  DEFAULT_SLIPPAGE_BPS: 100, // 100 basis points = 1%
} as const;
```

**Improvements:**
- Unified slippage configuration using basis points for consistency
- Added price staleness validation to prevent execution with stale
prices
- New `priceAtCalculation` and `maxSlippageBps` fields in `OrderParams`
- Provider validates price hasn't moved beyond tolerance before
execution
- Standardized slippage across market orders, position closing, and
TP/SL orders

**Slippage Validation Example:**
```typescript
// Provider checks price delta before order execution
const priceDeltaBps = Math.abs(
  ((currentPrice - priceAtCalculation) / priceAtCalculation) * 10000
);
if (priceDeltaBps > maxSlippageBps) {
  throw new Error(`Price moved too much: ${priceDeltaBps} bps`);
}
```

#### 3. Enhanced Order Validation

**Validation Improvements:**
- **USD as source of truth for minimum validation** - validates user's
exact USD input without recalculation
- Example: User enters $10 → validates $10 directly (no rounding errors)
- For full position closes (e.g., Close All), minimum validation is
skipped
- Added `skipValidation` flag to prevent validation flash during keypad
input
- Enhanced limit order validation to require price parameter

**Type System Updates:**
```typescript
export type OrderParams = {
  // Existing fields...
  size: string; // Now derived, provider recalculates from usdAmount

  // New hybrid approach fields
  usdAmount?: string; // Primary source of truth
  priceAtCalculation?: number; // For slippage validation
  maxSlippageBps?: number; // Slippage tolerance (e.g., 100 = 1%)

  // Updated documentation
  slippage?: number; // Now defaults to ORDER_SLIPPAGE_CONFIG.DEFAULT_SLIPPAGE_BPS / 10000
};
```

#### 4. Close Position Validation & Precision

**Problem Addressed:**
- Close positions were failing with "Minimum order size is $10" even
when closing 100% of small positions (e.g., closing a $5.23 position)
- Close position calculations used hardcoded decimal precision (6
decimals) instead of asset-specific `szDecimals`
- As part of the USD-as-source-of-truth refactor, close position
calculations needed the same precision improvements as order placement

**Solution - Full vs Partial Close Distinction:**

**Full Position Close (100%):**
- Added `isFullClose` flag to `OrderParams` type
- Set automatically when `size` parameter is omitted: `isFullClose:
!params.size`
- Skips USD validation and $10 minimum entirely
- Allows closing positions of any size (e.g., $5.23 position)

**Partial Position Close:**
- Still enforces $10 minimum validation
- Uses same USD validation logic as new orders
- Requires `currentPrice` or `usdAmount` for validation

**Close Amount Calculation Refactor:**
- Migrated `calculateCloseAmountFromPercentage` to USD as source of
truth
- Added required `szDecimals` parameter (removed dangerous defaults)
- Implemented post-rounding USD validation:
  ```typescript
  const actualUsd = tokenAmount * currentPrice;
  if (actualUsd < usdValue) {
    tokenAmount += 1 / multiplier; // Add 1 minimum increment
  }
  ```
- Now matches `calculatePositionSize` logic for consistency

**Type Changes:**
```typescript
export type OrderParams = {
  // ... existing fields
  isFullClose?: boolean; // Indicates closing 100% of position (skips validation)
};

// calculateCloseAmountFromPercentage now requires szDecimals
interface CloseAmountFromPercentageParams {
  percentage: number;
  positionSize: number;
  currentPrice: number;
  szDecimals: number; // REQUIRED - no longer optional
}
```

**Files Changed:**
- `controllers/types/index.ts` - Added `isFullClose` flag
- `utils/positionCalculations.ts` - Refactored to use USD as source of
truth with asset-specific precision
- `Views/PerpsClosePositionView/PerpsClosePositionView.tsx` - Added
`szDecimals` handling with loading state
- `controllers/providers/HyperLiquidProvider.ts` - Updated validation to
skip minimum for full closes

#### 5. Position Size Calculation Changes

**Rounding Behavior:**
- Changed from `Math.floor` to `Math.round` in `calculatePositionSize`
- More accurate position size calculation that rounds to nearest value
- Aligned with provider's recalculation logic for consistency

**Provider-Side Recalculation:**
```typescript
// In HyperLiquidProvider.placeOrder()
if (params.usdAmount && parseFloat(params.usdAmount) > 0) {
  const usdAmount = parseFloat(params.usdAmount);

  // Recalculate with fresh price
  finalPositionSize = usdAmount / currentPrice;

  // Apply same rounding as UI
  const multiplier = Math.pow(10, assetInfo.szDecimals);
  finalPositionSize = Math.round(finalPositionSize * multiplier) / multiplier;
}
```

#### 6. User Experience Improvements

**Input Handling:**
- Removed optimization calls from percentage/slider/max buttons
- Fixed input clamping to only apply for keypad input (not
percentage/slider/max)
- Reduced unnecessary re-renders and calculations
- Skip validation during active input to prevent flickering error
messages

**Code Cleanup:**
- Removed FinalizationRegistry polyfill from `shim.js` (no longer needed
by updated dependencies)
- Removed unused `findOptimalAmount` and
`findHighestAmountForPositionSize` functions
- Cleaned up debounced optimization logic from form handlers

### Migration Path

**Backward Compatibility:**
- `size` field still present in `OrderParams` for backward compatibility
- Provider falls back to legacy size calculation if `usdAmount` is not
provided
- Existing orders and integrations continue to work

**Hybrid Approach:**
Orders now pass both `usdAmount` (primary) and `size` (derived):
```typescript
const orderParams: OrderParams = {
  coin: 'BTC',
  isBuy: true,
  size: positionSize, // Kept for compatibility, recalculated by provider
  usdAmount: orderForm.amount, // USD as source of truth
  priceAtCalculation: assetData.price, // For validation
  maxSlippageBps: 100, // 1% tolerance
  // ... other fields
};
```

### Files Changed

**Core Logic (276 additions, 290 deletions):**
- `app/components/UI/Perps/controllers/providers/HyperLiquidProvider.ts`
(+148 lines)
  - Hybrid USD-based order placement with price validation
  - Standardized slippage across all order types
  - Position size recalculation at execution time
- `app/components/UI/Perps/utils/orderCalculations.ts` (-149 lines)
  - Removed `findOptimalAmount` and `findHighestAmountForPositionSize`
  - Changed `Math.floor` to `Math.round` for position size calculation
- `app/components/UI/Perps/hooks/usePerpsOrderForm.ts` (-71 lines)
  - Removed `optimizeOrderAmount` function and related logic
  - Simplified amount initialization
- `app/components/UI/Perps/hooks/usePerpsOrderValidation.ts` (+28 lines)
  - Added `skipValidation` and `originalUsdAmount` parameters
  - Improved minimum order size validation with original USD input

**UI Components:**
- `app/components/UI/Perps/Views/PerpsOrderView/PerpsOrderView.tsx`
(+/-54 lines)
  - Removed optimization calls from input handlers
  - Added `skipValidation` flag during input focus
  - Pass `usdAmount` and price validation params to provider
  - Fixed input clamping behavior

**Configuration:**
- `app/components/UI/Perps/constants/perpsConfig.ts` (+10 lines)
  - Added `ORDER_SLIPPAGE_CONFIG` constant
- `app/components/UI/Perps/constants/hyperLiquidConfig.ts` (-1 line)
  - Removed legacy slippage configuration

**Types & Validation:**
- `app/components/UI/Perps/controllers/types/index.ts` (+9 lines)
  - Updated `OrderParams` type with USD-based fields
- `app/components/UI/Perps/utils/hyperLiquidValidation.ts` (+9 lines)
  - Enhanced validation for limit orders
  - Added minimum order size tolerance
- `app/components/UI/Perps/utils/hyperLiquidValidation.test.ts` (+29
lines)
  - Added tests for limit order price validation

**Cleanup:**
- `shim.js` (-18 lines)
  - Removed FinalizationRegistry polyfill

## **Changelog**

CHANGELOG entry: Improved Perps order precision and validation by using
USD amounts as source of truth and standardizing slippage management

## **Related issues**

Fixes:
[TAT-1902](https://consensyssoftware.atlassian.net/browse/TAT-1902) -
Investigate and resolve order placement issue for specific token pairs

**How this PR fixes TAT-1902:**
The USD-as-source-of-truth refactor directly addresses order placement
failures for specific token pairs by:
- Recalculating position size at execution time with fresh market prices
instead of using stale UI calculations
- Using asset-specific `szDecimals` precision throughout (no more
hardcoded 6 decimals)
- Eliminating optimization logic that could produce invalid amounts near
precision boundaries
- Validating orders with the exact USD amount entered by the user,
preventing precision loss from multiple conversions

This ensures orders are calculated with the most current price and
correct precision for each token pair, preventing the placement failures
that occurred with the previous approach.

## **Manual testing steps**

```gherkin
Feature: Perps Order Placement with USD as Source of Truth

  Scenario: User places a market order with precise USD amount
    Given user is on the Perps trading screen
    And user has sufficient balance

    When user enters "$100" USD amount via keypad
    And user selects "Market" order type
    And user taps "Place Order"

    Then order is placed with position size calculated from fresh market price
    And order execution succeeds without "insufficient margin" errors
    And no validation flickering occurs during input

  Scenario: User places order near minimum amount threshold
    Given user is on the Perps trading screen
    And market price causes calculated value to be near $10 minimum

    When user enters an amount that rounds to ~$9.99-$10.01
    And user places the order

    Then validation passes with 1% tolerance
    And no flickering validation errors appear

  Scenario: Price moves during order placement
    Given user has entered order details
    And calculated position size at price $50,000

    When market price moves to $50,500 (>1% move)
    And user places the order

    Then order is rejected with "Price moved too much" error
    And user is prompted to review and resubmit

  Scenario: User places limit order without price
    Given user is on the Perps trading screen
    And user selects "Limit" order type
    And user does not enter a limit price

    When user attempts to place order

    Then validation error displays "Price is required for limit orders"

  Scenario: User uses percentage buttons
    Given user is on the Perps trading screen
    And user has $1000 available balance

    When user taps "25%" button

    Then amount field shows "$250"
    And no optimization is triggered
    And position size is calculated correctly

  Scenario: User adjusts amount with slider
    Given user is on the Perps trading screen

    When user drags the amount slider

    Then amount updates in real-time
    And validation is skipped during interaction
    And validation applies after slider is released

  Scenario: User enters amount exceeding maximum
    Given user has $1000 available balance at 10x leverage
    And maximum possible order is $10,000

    When user enters "$15,000" via keypad
    And user dismisses the keypad

    Then amount is automatically clamped to "$10,000"
    And validation message explains the limit

  Scenario: User closes 100% of a position worth less than minimum
    Given user has an open position worth $5.23
    And minimum order size is $10

    When user taps "Close Position" button
    And selects "100%" (full close)
    And confirms the close

    Then position closes successfully
    And no minimum order size error appears
    And full position value is returned

  Scenario: User closes partial position below minimum
    Given user has an open position worth $100
    And minimum order size is $10

    When user attempts to close $8 worth of the position
    And confirms the close

    Then validation error displays "Minimum order size is $10"
    And close operation is prevented
```

## **Screenshots/Recordings**

### **Before**
- Orders occasionally failed with "insufficient margin" despite UI
showing valid amounts
- Validation messages flickered during input on low-priced tokens
- Complex optimization logic ran on every input change
- Position size calculated once in UI, potentially stale at execution

### **After**
- Consistent order execution with USD as source of truth
- No validation flickering with 1% tolerance on minimum amounts
- Simplified input handling without optimization overhead
- Position size recalculated with fresh price at execution time
- Price staleness validation prevents execution with stale prices

<!-- Add screenshots/recordings here if available -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---

## **Technical Notes for Reviewers**

### Critical Changes to Review

1. **Rounding Change in `calculatePositionSize`**
   - Changed from `Math.floor` to `Math.round`
   - Verify this doesn't cause issues with existing positions or orders
   - Check that rounding behavior matches exchange requirements

2. **Backward Compatibility**
   - `OrderParams.size` still present but recalculated by provider
   - Verify existing integrations continue to work
   - Test with and without `usdAmount` parameter

3. **Slippage Validation**
   - Price staleness check may reject valid orders in volatile markets
   - Default 1% tolerance (100 bps) - verify this is appropriate
   - Check error messages are clear to users

4. **Minimum Order Size Validation**
   - USD as source of truth - validates exact user input ($10 ≥ $10)
   - No tolerance needed when using usdAmount parameter
- **Full position closes (100%)** skip validation entirely via
`isFullClose` flag
   - **Partial position closes** enforce $10 minimum validation
   - **New positions** enforce $10 minimum validation
- Close position calculations use same USD validation logic as order
placement

5. **Input Clamping Logic**
   - Now only clamps for keypad input, not percentage/slider/max
   - Verify this doesn't break max amount validation
   - Test with various input methods

### Testing Recommendations

- Test with various token prices (low, medium, high)
- Test near minimum order size ($10) with price fluctuations
- Test with high leverage where rounding matters more
- Test order placement during price volatility
- Test limit orders with missing/invalid prices
- Verify no "insufficient margin" errors for valid amounts
- Check validation doesn't flicker during keypad input


[TAT-1902]:
https://consensyssoftware.atlassian.net/browse/TAT-1902?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Switches order/close flows to USD-as-source-of-truth with
provider-side size recalculation and unified slippage, improves
validation/precision, removes optimization logic, and updates
hooks/tests/docs.
> 
> - **Core trading/provider**:
> - Use USD as source of truth; provider recalculates size at execution
with fresh price and asset `szDecimals` (`HyperLiquidProvider.ts`).
> - Add slippage config via `ORDER_SLIPPAGE_CONFIG` (default 100 bps)
and price-staleness validation; pass `usdAmount`, `priceAtCalculation`,
`maxSlippageBps` through `OrderParams`.
> - Refactor order build/format helpers into `orderCalculations`
(`calculateFinalPositionSize`, `calculateOrderPriceAndSize`,
`buildOrdersArray`).
> - Support full-close bypass of $10 minimum via `isFullClose`;
propagate slippage params in close flows.
> - **Validation & precision**:
> - `calculatePositionSize`/close calculations use asset precision,
round to nearest, and ensure post-rounding USD meets target.
> - `validateOrder` now validates minimums from USD, requires price for
limit orders, and tolerates full closes.
> - Remove `findOptimalAmount`/related logic and old slippage from
`hyperLiquidConfig`.
> - **UI/hooks**:
> - `PerpsOrderView`/`PerpsClosePositionView`: pass USD + slippage
params; skip validation during input; clamp only for keypad; use market
data with fallback decimals.
> - `usePerpsMarketData` accepts `{ asset, showErrorToast }` and
auto-toasts on errors; expose loading.
> - `usePerpsOrderValidation`/`usePerpsClosePositionValidation`: add
`skipValidation`, use original USD for min checks.
> - **Types/constants**:
> - Extend `OrderParams`/`ClosePositionParams` with
USD/slippage/full-close fields; add
`DECIMAL_PRECISION_CONFIG.FALLBACK_SIZE_DECIMALS` and
`ORDER_SLIPPAGE_CONFIG`.
> - **Tests & docs**:
> - Update extensive tests to new params, rounding, and hook signatures;
adjust provider tests for price-required errors.
> - Refresh trading guide (market order/slippage sections) and fix
reference paths.
> - **Cleanup**:
> - Remove FinalizationRegistry polyfill from `shim.js`; simplify order
form by dropping optimization APIs.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fda1210. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: dylanbutler1 <99672693+dylanbutler1@users.noreply.github.com>
…22392)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

This PR aims to fix recipient input to show multiline for selected
address in send flow

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Fix recipient to be shown multi-line in send flow

## **Related issues**

Fixes: #22207

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<img width="568" height="1084" alt="Screenshot 2025-11-10 at 12 03 50"
src="https://github.com/user-attachments/assets/f8f0da96-2505-4c76-b77c-f904fcab3d6d"
/>


### **After**

<img width="568" height="1084" alt="Screenshot 2025-11-10 at 12 03 43"
src="https://github.com/user-attachments/assets/56c76b7c-a0c9-4640-9f02-bc3b446eed68"
/>


## **Pre-merge author checklist**

- [X] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [X] I've completed the PR template to the best of my ability
- [X] I’ve included tests if applicable
- [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [X] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Replaces direct TextField props with a custom Input element to force
single-line recipient addresses and prevent multiline behavior.
> 
> - **Confirmations › RecipientInput
(`app/components/Views/confirmations/components/recipient-input/recipient-input.tsx`)**
> - Use `TextField` `inputElement` with `foundation/Input` to control
behavior.
> - Configure single-line input: `multiline={false}`,
`numberOfLines={1}`, `scrollEnabled={false}`,
`textAlignVertical="center"`, `textBreakStrategy="simple"`.
> - Move input props (value, change handlers,
autocorrect/spellcheck/autocomplete/capitalize, placeholder, autofocus,
testID) onto `Input`.
> - Apply `INPUT_STYLE_OVERRIDE` to remove height/lineHeight and pad
adjustments; disable state styles; set `textVariant` via
`TOKEN_TEXTFIELD_INPUT_TEXT_VARIANT`.
> - Keep start/end accessories (To label, Clear/Paste buttons)
unchanged.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e06f20c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

This PR aims to add PPOM validation requests for deeplinks.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: null

## **Related issues**

Fixes: MetaMask/mobile-planning#2370
Fixes: #17358

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [X] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [X] I've completed the PR template to the best of my ability
- [X] I’ve included tests if applicable
- [X] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [X] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Integrates PPOM validation into deeplink transfer/approve flows,
generating a securityAlertId and passing it to addTransaction, with
refactors and tests.
> 
> - **Deeplink handling
(`app/components/Views/confirmations/utils/deeplink.ts`)**:
> - Add `validateWithPPOM` to build a PPOM request (with uuid-based
`securityAlertId`) and call `ppomUtil.validateRequest`.
> - Pass returned `securityAlertResponse` to `addTransaction` for both
native and ERC20 transfers.
> - Refactor tx construction to derive `txParams` and `transactionType`;
downgrade duplicate-request log from error to log.
> - **Approve flow
(`app/core/DeeplinkManager/TransactionManager/approveTransaction.ts`)**:
> - Compute `chainId`/`networkClientId`, call `validateWithPPOM`, and
include `securityAlertResponse` in `addTransaction`.
> - **Tests**:
> - Extend deeplink and approve tests to mock PPOM and UUID, assert PPOM
validation payload, `securityAlertResponse`, and `networkClientId`
wiring.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
daa4941. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Fix scrolling in the MetaMask Pay asset picker on Android.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
[#6147](MetaMask/MetaMask-planning#6147)

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Switches asset picker and network filter to use
react-native-gesture-handler ScrollView to fix Android scrolling.
> 
> - **Mobile UI**:
> - Replace `react-native` `ScrollView` with
`react-native-gesture-handler` in
`app/components/Views/confirmations/components/network-filter/network-filter.tsx`
and
`app/components/Views/confirmations/components/send/asset/asset.tsx`.
>   - Minor `ScrollView` prop formatting cleanup in `asset.tsx`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
a7e0901. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

Show additional details in Predict claim confirmation if single won
position.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: [6004](MetaMask/MetaMask-planning#6004)

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

<img width="300" alt="Claim Single"
src="https://github.com/user-attachments/assets/088c99d2-d3b7-4852-9009-357ad4ccd546"
/>

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Enhances Predict claim footer to display detailed info for a single
win and refactors component structure with accompanying tests.
> 
> - **Predict claim footer** (`predict-claim-footer.tsx`):
> - Show single-win details: large token avatar, market title, formatted
fiat amount, and outcome.
> - Refactor into `SingleWin` and `MultipleWinnings` subcomponents;
memoize fiat formatting; return null when no won positions.
> - **Tests**:
> - Add tests for single-win extra info, avatar count (max 3), button
press, and fallback selected address.
> - Update mocks/render helper to support `singlePosition` and
`accountMock`.
> - Remove predict-claim footer render check from generic `Footer` tests
and drop unused `TransactionType` import.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8073f69. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
…22517)

## **Description**

This PR fixes an issue in the Perps Market Tabs component where the
TabsList wasn't properly re-rendering when the number of visible tabs
changed.


## **Changelog**


CHANGELOG entry: Fixed an issue where perps market tabs would not update
correctly when the number of visible tabs changed

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-1982

## **Manual testing steps**

```gherkin
Feature: Perps Market Tabs Rendering

  Scenario: user switches between market states that affect tab visibility
    Given user is on the perps market details view with active position
    
    When user closes their position or opens new positions
    Then the tabs should correctly update to reflect the current state (position tab should appear/disappear)
    And the active tab selection should remain consistent
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->


### **Before**

<!-- [screenshots/recordings] -->
No visible change

### **After**

<!-- [screenshots/recordings] -->
No visible change

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Ensure `TabsList` remounts when the number of visible tabs changes by
incorporating `tabsToRender.length` into the component key.
> 
> - **Perps UI**:
> - **Tabs re-rendering**: Update `tabsKey` in `PerpsMarketTabs.tsx` to
`tabs-${tabs.length}-${tabsToRender.length}` so `TabsList` remounts when
the visible tab count changes.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e03f2b2. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

- Introduced PortManager to handle port allocation and release for
various servers.
- Updated Ganache, MockServerE2E, DappServer, CommandQueueServer,
FixtureServer, and AnvilManager to utilize PortManager for setting and
releasing ports.
- Added methods to set server ports and handle server status in
respective classes.
- Implemented retry logic for starting resources with automatic port
management to avoid conflicts.
- Updated FixtureUtils to include new port management functions and
ensure correct RPC URLs are used based on allocated ports.
- Update swaps tests to use Anvil (from ganache)

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds PortManager-driven dynamic port allocation with retries and
platform handling, refactors test servers/utilities to use it, migrates
swaps tests to Anvil, and standardizes “Network fee” casing.
> 
> - **E2E Infra (Port Management)**:
> - Introduces `PortManager` for dynamic/random port allocation
(single/multi-instance), release, and BrowserStack fallbacks; adds
robust retry start helpers (`startResourceWithRetry`,
`startMultiInstanceResourceWithRetry`).
> - Implements Android `adb reverse` mapping, iOS LaunchArgs, and
MockServer host-side fallback→actual port translation.
> - **Server/Utility Refactors**:
> - Update `Ganache`, `AnvilManager`, `FixtureServer`,
`CommandQueueServer`, `DappServer`, `MockServerE2E` to `setServerPort`,
track status, and release ports; `DappServer` supports multi-instance.
> - Revamps `FixtureUtils`/`FixtureHelper` APIs (`getDappUrl*`,
`get*PortForFixture`, RPC/Dapp URL rewrites) and improves
network-store/shim host resolution.
> - **Tests**:
>   - New comprehensive `PortManager.test.ts`.
> - Migrate swaps tests to Anvil; update fixtures and helpers to new
APIs; remove manual reverse logic.
> - **UX/Text**:
> - Standardize casing to `Network fee` across tests and
`locales/languages/en.json`.
> - **Misc**:
>   - Adjust allowlist/mocks; minor README formatting.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f63e958. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: fix error message when trying to import an SRP with an
account that is already imported via private key

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/MUL-491

## **Manual testing steps**

1. Import private key account
2. Import SRP that includes this private key account
3. Verify that the error message "The account you are trying to import
is a duplicate." is shown

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<img width="925" height="903" alt="image"
src="https://github.com/user-attachments/assets/77abb409-feac-4ba4-92bd-387d122928dd"
/>

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds explicit handling and user-facing message when an SRP import
fails due to a duplicate account, with tests and i18n updates.
> 
> - **Import SRP View
(`app/components/Views/ImportNewSecretRecoveryPhrase/index.tsx`)**:
> - Refactor error handling to `switch` and add case for
`KeyringController - The account you are trying to import is a
duplicate`, showing `error_duplicate_account` alert.
> - **Tests
(`app/components/Views/ImportNewSecretRecoveryPhrase/index.test.tsx`)**:
> - Add test to assert duplicate account import error triggers the
correct alert.
> - **Localization (`locales/languages/en.json`)**:
> - Add `import_new_secret_recovery_phrase.error_duplicate_account`
copy.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f43d802. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
As part of developing the "Trending" feature we needed to add a global
search that would allow searching amongst trending tokens, perps,
trending predictions...

I have developed a MODULAR search hook and global search that allows
searching across all existing sections and allows for easy integration
of new sections.

If a new section is added, the user will have to only modify the
configuration in `exploreSearchConfig` like this:
<img width="387" height="328" alt="image"
src="https://github.com/user-attachments/assets/e00ce4fb-3831-422e-80a3-30d2436cddad"
/>

and add the necessary hook inside `useExplorerSearch`:
<img width="416" height="449" alt="image"
src="https://github.com/user-attachments/assets/78366050-4ab8-4859-ad09-095077be89cf"
/>

Everything else is handled automatically which makes it **easy** for
developers to add new configurations

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: added new trending search functionality

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/ASSETS-1528 &
https://consensyssoftware.atlassian.net/browse/ASSETS-1527

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**



https://github.com/user-attachments/assets/d912d5d0-4cd1-45c9-8a94-459d437f03aa



## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces an Explore Search flow with a modular search hook, UI
components, navigation, i18n, and tests, enabling search across tokens,
perps, and predictions from the Trending tab.
> 
> - **Trending / Explore Search**:
>   - **UI**:
> - Add `ExploreSearchBar` and `ExploreSearchScreen` with
`ExploreSearchResults` list (headers, items, skeletons).
> - Integrate search entry in `TrendingView` (button + navigation), wrap
with `PerpsStreamProvider`.
>   - **Hook & Config**:
> - Add generic `useExploreSearch` (200ms debounce, top-3 on empty,
per-section filtering).
> - Define configurable sections in `exploreSearchConfig` for `tokens`,
`perps`, `predictions` with item renderers and key extractors.
>   - **Navigation**:
> - Add route `Routes.EXPLORE_SEARCH`; register in `TrendingView` stack;
update imports in `MainNavigator`.
>   - **i18n**:
> - Extend `trending` strings: `search_placeholder`, `perps`,
`predictions`, `no_results`.
>   - **Tests**:
> - Add tests for `ExploreSearchBar`, `ExploreSearchResults`,
`useExploreSearch`, and update `TrendingView` tests for search button
and navigation.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b35671b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
## **Description**

### Summary

Adds Segment analytics tracking for QR Scanner usage to measure feature
adoption and understand user scanning patterns.

### Events Added

- **QR Scanner Opened** - Tracks when QR scanner is opened with camera
permission granted
- **QR Scanned** - Tracks all QR code scan attempts with
success/failure, type classification, and detailed scan results

### Properties

**QR Scanned** includes:
- `scan_success` (boolean) - Technical success: camera successfully read
the QR code
- `qr_type` (string) - Classification: `"seed phrase"` | `"private key"`
| `"send flow"` | `"wallet connect"` | `"deeplink"` | `"url"`
- `scan_result` (string) - Functional outcome: `"completed"` |
`"deeplink_handled"` | `"url_navigation_confirmed"` |
`"unrecognized_qr_code"` | `"invalid_address_format"` |
`"url_navigation_cancelled"` | `"wallet_locked"`

### Use Cases

- Measure scanner success rate (filter by `scan_result` to exclude
failures)
- Understand QR type distribution (`qr_type` breakdown)
- Debug scan failures (`scan_result` analysis)
- Improve UX by identifying common failure patterns
- Track WalletConnect connection initiation via QR codes

### Implementation Details

#### QR_SCANNER_OPENED
- Fires once per scanner session when permission is granted and camera
is available
- Includes global properties only 

#### QR_SCANNED

- Tracks all 6 QR code types with appropriate success/failure states:
- Seed Phrase 
- Private Key 
- Send Flow 
- Wallet Connect 
- Deeplink 
- URL 

Segment PR: Consensys/segment-schema#360

## **Changelog**

CHANGELOG entry:  Added segment events for QR scanning

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TMCU-66

## **Manual testing steps**

```gherkin
Feature: QR Scanner Metrics Tracking

  Scenario: QR Scanner Opened event fires when scanner is accessed
    Given the user is on the MetaMask Mobile homepage
    And camera permissions are granted
    
    When user taps the QR scanner icon
    Then the QR scanner opens
    And "QR Scanner Opened" event is tracked with no custom properties
    And the event appears in console logs and Segment debugger

  Scenario: user scans a seed phrase QR code
    Given the QR scanner is open
    And a QR code containing a 12-word seed phrase is displayed
    
    When user scans the seed phrase QR code
    Then "QR Scanned" event is tracked
    And scan_success property is true
    And qr_type property is "seed phrase"

  Scenario: user scans a private key QR code
    Given the QR scanner is open
    And a QR code containing "0x" followed by 64 hex characters is displayed
    
    When user scans the private key QR code
    Then "QR Scanned" event is tracked
    And scan_success property is true
    And qr_type property is "private key"

  Scenario: user scans a valid Ethereum address in send flow
    Given the user is in the Send Flow screen
    And user taps the QR scanner icon
    And a QR code containing a valid Ethereum address is displayed
    
    When user scans the address QR code
    Then "QR Scanned" event is tracked
    And scan_success property is true
    And qr_type property is "send flow"

  Scenario: user scans an invalid address in send flow
    Given the user is in the Send Flow screen
    And user taps the QR scanner icon
    And a QR code containing invalid address text is displayed
    
    When user scans the invalid QR code
    Then "QR Scanned" event is tracked
    And scan_success property is false
    And qr_type property is "send flow"
    And an error alert is displayed

  Scenario: user scans a WalletConnect URI
    Given the QR scanner is open
    And a QR code containing a WalletConnect URI (wc:...) is displayed
    
    When user scans the WalletConnect QR code
    Then "QR Scanned" event is tracked
    And scan_success property is true
    And qr_type property is "wallet connect"

  Scenario: user scans a MetaMask deeplink
    Given the QR scanner is open
    And a QR code containing "metamask-sdk://" or "metamask-sync:" is displayed
    
    When user scans the deeplink QR code
    Then "QR Scanned" event is tracked
    And scan_success property is true
    And qr_type property is "deeplink"

  Scenario: user scans a URL and confirms navigation
    Given the QR scanner is open
    And a QR code containing "https://example.com" is displayed
    
    When user scans the URL QR code
    And user taps "Continue" on the confirmation dialog
    Then "QR Scanned" event is tracked
    And scan_success property is true
    And qr_type property is "url"

  Scenario: user scans a URL and cancels navigation
    Given the QR scanner is open
    And a QR code containing "https://example.com" is displayed
    
    When user scans the URL QR code
    And user taps "Cancel" on the confirmation dialog
    Then "QR Scanned" event is tracked
    And scan_success property is false
    And qr_type property is "url"
```

## **Screenshots/Recordings**

### Seed Phrase Flow


https://github.com/user-attachments/assets/6f8357c3-f1e4-467b-8c6a-9188a71948f4

### Private Key Flow


https://github.com/user-attachments/assets/1ce6f4cf-62e7-4bde-bce5-8d14bf9fba50

### Send Flow - Valid Address

__Send flow is currently broken there is a PR
[here](#21498) to fix
the issue. The video is just a demonstration of the event being
tracked__


https://github.com/user-attachments/assets/909d5687-9789-41b5-be45-4503a1bb0e53

### Send Flow - Unknown Address


https://github.com/user-attachments/assets/fd15c33c-e90a-4427-a7ed-684a741a075f

### Send Flow - Invalid Address


https://github.com/user-attachments/assets/34f27530-b1d6-4035-9713-19955c501090

### Wallet Connect


https://github.com/user-attachments/assets/b41f9fcc-a6a1-4440-9bba-63be4305ad4e

### SDK

### Website - Accept


https://github.com/user-attachments/assets/d7f00d09-a03a-4e6c-9056-99575ed2302d

### Website - Cancel


https://github.com/user-attachments/assets/2c3d9cff-36cd-475c-958e-e16034030e46

### **Before**

`~`

### **After**

`~`

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.




<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds MetaMetrics tracking for QR Scanner open/scan with standardized
properties and QR type detection, plus comprehensive tests and event
definitions.
> 
> - **Analytics**:
> - Add `QR_SCANNER_OPENED` and `QR_SCANNED` to
`core/Analytics/MetaMetrics.events.ts`.
>   - Track scanner open when permission granted and camera available.
> - Track scans with properties: `scan_success`, `qr_type`,
`scan_result` across types (`seed phrase`, `private key`, `send flow`,
`wallet connect`, `deeplink`, `url`), including outcomes (e.g., URL
confirm/cancel, wallet locked, invalid address, deeplink handled).
> - **QR Scanner**:
> - New `app/components/Views/QRScanner/constants.ts` for event keys, QR
types, and scan result values.
> - New `getQRType` in `app/components/Views/QRScanner/utils.ts` to
classify scanned content.
> - Update `app/components/Views/QRScanner/index.tsx` to emit events,
handle URL redirection flow, SDK/deeplink handling, and wallet-locked
checks; minor typing/refactors.
> - **Tests**:
>   - Expand `index.test.tsx` to validate event emission for all paths.
>   - Add `utils.test.ts` to verify `getQRType` classification logic.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e419028. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR enables live PnL (Profit and Loss) updates in the Perps Market
Tabs by subscribing to real-time price updates from the WebSocket
stream.

## **Changelog**

CHANGELOG entry: Fixed live PnL updates in Perps market tabs to reflect
real-time price changes

## **Related issues**

Fixes: https://consensyssoftware.atlassian.net/browse/TAT-1946

## **Manual testing steps**

```gherkin
Feature: Live PnL updates in Perps Market Tabs

  Scenario: user views position with live PnL updates
    Given user has an open perpetual position
    And user is on the Perps Market Tabs screen
    
    When market price changes
    Then the unrealized PnL and ROE values update in real-time
    And the position card reflects current market conditions
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

No visible changes

### **After**

No visible changes

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Enable live PnL updates by passing `useLivePnl: true` to
`usePerpsLivePositions` in `PerpsMarketTabs.tsx`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
32657d9. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Nicholas Smith <nick.smith@consensys.net>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

This PR introduces **AppStateAPI**, a new centralized API for monitoring
React Native app state changes (foreground/background/inactive) and
managing lock timers.

### **Reason for the change**

Currently, app state monitoring is scattered across the codebase with
direct React Native `AppState` imports in multiple components. This
creates tight coupling and makes it difficult to:
- Track which components are monitoring app state
- Test app state behavior consistently
- Manage lock timers in a centralized way
- Ensure proper cleanup of native listeners

### **The improvement/solution**

**AppStateAPI** provides a clean, singleton-based API with the following
benefits:

1. **Centralized Monitoring**: Single source of truth for app state
changes
2. **EventEmitter Pattern**: Components can subscribe to specific events
(`foreground`, `background`, `inactive`, `change`) without tight
coupling
3. **Separation of Concerns**: The API only monitors and emits events—it
does NOT perform locking. State machines/sagas handle actual locking
logic
4. **Lock Timer Management**: Built-in timer functionality for auto-lock
features with background timer support
5. **Clean Lifecycle**: Explicit `initialize()` and `cleanup()` methods
with proper native listener management
6. **Type Safety**: Full TypeScript implementation with exported types

### **Key Features**

- **App State Events**: `foreground`, `background`, `inactive`, `change`
- **Lock Timer**: `startLockTimer(duration, callback)`,
`clearLockTimer()`, `getLockTimerRemaining()`, `isLockTimerActive()`
- **State Queries**: `getCurrentAppState()`, `isAppInForeground()`,
`isAppInBackground()`, `isAppInactive()`
- **Lifecycle**: `initialize()`, `cleanup()`, `isInitialized()`

### **Architecture Summary**

| Component | Status | Lines | Purpose |

|------------------------|--------|-------|----------------------------------|
| AppStateAPI | ✅ New | 267 | Monitor app state & lock timers |
| Authentication.ts | ✅ Existing | 1230 | Keep using (works well) |
| State Machines (Sagas) | 🔄 Update | 234 | Will use AppStateAPI events
|
| LockManagerService | ⚠️ Deprecate | 122 | Gradually migrate away |

This PR includes debug instrumentation in `Root/index.tsx` for manual
testing (dev mode only).

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Refs: [Add issue number here]

## **Manual testing steps**

```gherkin
Feature: AppStateAPI monitors app state changes

  Scenario: Developer tests app state monitoring in development mode
    Given the app is running in development mode
    And AppStateAPI is initialized in Root component
    
    When the app is launched
    Then console logs should show "APPSTATEAPI: 🔵 Initializing AppStateAPI for manual testing"
    And console logs should show "APPSTATEAPI: 🔵 Starting 10-second lock timer"
    And console logs should display current app state as "active"

  Scenario: Developer backgrounds the app
    Given the app is running in foreground
    And AppStateAPI is initialized
    
    When the developer backgrounds the app
    Then console logs should show "APPSTATEAPI: 🔴 App BACKGROUNDED"
    And the background event should be emitted with state "background"

  Scenario: Developer foregrounds the app
    Given the app is running in background
    And AppStateAPI is initialized
    
    When the developer brings the app to foreground
    Then console logs should show "APPSTATEAPI: 🟢 App FOREGROUNDED"
    And the foreground event should be emitted with state "active"

  Scenario: Lock timer expires while app is backgrounded
    Given the app is running
    And a 10-second lock timer has been started
    
    When the developer backgrounds the app for more than 10 seconds
    Then console logs should show "APPSTATEAPI: ⏰ Lock timer EXPIRED"
    And the timer callback should be invoked

  Scenario: Developer checks AppStateAPI state queries
    Given the app is running
    And AppStateAPI is initialized
    
    When the developer views the console logs
    Then logs should show "Is in foreground?" with a boolean value
    And logs should show "Lock timer active?" with a boolean value
    And logs should show the current app state

  Scenario: AppStateAPI cleanup on unmount
    Given the app is running with AppStateAPI initialized
    
    When the Root component unmounts
    Then console logs should show "Cleaning up AppStateAPI"
    And all event listeners should be removed
    And lock timers should be cleared
```

## **Screenshots/Recordings**


https://github.com/user-attachments/assets/b9dfe51e-9ab9-45cc-802d-7f5fd9281c38

### **Before**

No centralized app state monitoring—components directly import
`AppState` from React Native.

### **After**

New `AppStateAPI` provides centralized monitoring with console output in
dev mode:

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduce a singleton AppState service that emits app state events and
manages a lock timer, with comprehensive tests and exports.
> 
> - **Core**:
> - **`app/core/AppStateService/AppStateService.ts`**: New singleton
`AppStateServiceImplementation` (EventEmitter-based) to monitor React
Native `AppState` and emit `foreground`, `background`, `inactive`, and
`change` events.
> - Provides lifecycle methods: `initialize()`, `cleanup()`,
`isInitialized()`.
> - Adds lock timer utilities: `startLockTimer()`, `clearLockTimer()`,
`getLockTimerRemaining()`, `isLockTimerActive()` using
`react-native-background-timer`.
>     - Exports singleton `AppStateService` and `AppStateStatus` type.
> - **Exports**:
> - **`app/core/AppStateService/index.ts`**: Re-exports service,
implementation, and types.
> - **Tests**:
> - **`app/core/AppStateService/AppStateService.test.ts`**:
Comprehensive unit tests mocking React Native and background timer to
verify initialization/cleanup, event emissions, lock timer behavior, and
state query helpers.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
574d3df. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**
Current BUGBOT rules and are too verbose and don't consistently run in
the pipeline without manual intervention. This change updates the file
structure as per the Cursor docs and simplifies the rule.

1. Changes BUGBOT file location for more consistent ci running
2. Replaces verbose rules with simple rules and adds markdown links so
Cursor can read them.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
3. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**
This test fork repo shows the rule now hits every Unit Test violation in
the Unit Testing Guidelines. Including

Test naming violations
AAA pattern violations
TypeScript type violations
Import/require violations
Test isolation violations
Assertion quality violations
Test complexity violations


https://github.com/michaelmccallam/metamask-mobileBugbotTest/pull/6/files

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**
Didn't pick up on the rules consistently 

<!-- [screenshots/recordings] -->

### **After**
Now picks up on each rule in the Unit Testing Guidelines and calls it
out in the comments.
<img width="730" height="441" alt="Screenshot 2025-11-08 at 09 50 23"
src="https://github.com/user-attachments/assets/ffd7a768-d012-49ae-92ec-e05a67266c5e"
/>


<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [x] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [x] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Moves BUGBOT rules to `.cursor/BUGBOT.md` and streamlines content,
updating test file pattern and guideline link.
> 
> - **BUGBOT rules**:
> - **Relocation**: Move from `.cursor/rules/BUGBOT.md` to
`.cursor/BUGBOT.md`.
> - **Simplification**: Replace verbose rule set with concise core
mission and minimal execution protocol.
> - **Testing pattern**: Update naming pattern to
``*.test.{ts,tsx,js,jsx}``.
> - **Guidelines link**: Reference `rules/unit-testing-guidelines.mdc`
from new location.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
6949b1f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
# Predict Buy: Rewards Display and Fee Consolidation

## Overview

This PR adds rewards point estimation and consolidates fee display in
the Predict Buy confirmation screen. Users can now see estimated
MetaMask Rewards points they'll earn from their transaction, and view
detailed fee breakdowns through an intuitive bottom sheet.

CHANGELOG entry: null


https://github.com/user-attachments/assets/cf20a4e3-1375-4f9b-97ff-c75a3d68f737

## Changes

### 🎁 Rewards Integration

- **Added "Est. points" row** to the Predict Buy confirmation screen
  - Displays estimated rewards points based on MetaMask fee
- **Calculation**: `Math.round(metamaskFee * 100)` (1 point per cent
spent on MM fee)
  - Position: Last row after "Total"
  - White text with gray info icon for consistency
  - Reuses `RewardsAnimations` component from Swap/Bridge features
- Conditional display based on `rewardsEnabled` feature flag and
transaction amount

### 💰 Fee Display Consolidation

- **Consolidated two fee rows into single "Fees" row**
  - Previously: Separate "Provider fee" and "MetaMask fee" rows
  - Now: Single "Fees" row showing sum of both fees
  - Added gray info icon that opens detailed breakdown

- **New Fee Breakdown Bottom Sheet** (`PredictFeeBreakdownSheet`)
  - Displays individual fee breakdown:
    - Polymarket fee (provider fee)
    - MetaMask fee
  - Opens when user taps info icon next to "Fees"
  - Closes without navigating back (uses `shouldNavigateBack={false}`)

### 🎨 UI/UX Improvements

- **Fee Summary Row Order**:
  1. Fees (consolidated, with info icon)
  2. Total
  3. Est. points (when rewards enabled)

- **Styling**:
  - Est. points text: White (`TextColor.Default`)
  - Info icons: Gray (`IconColor.Alternative`)
  - Consistent with design system

## Technical Details

### Files Modified

#### Components

- **`PredictBuyPreview.tsx`**
  - Import `selectRewardsEnabledFlag` selector
  - Calculate `estimatedPoints` from `metamaskFee`
  - Add `isFeeBreakdownVisible` state
  - Add `handleFeesInfoPress` and `handleFeeBreakdownClose` callbacks
  - Pass rewards props to `PredictFeeSummary`
  - Conditionally render `PredictFeeBreakdownSheet`

- **`PredictFeeSummary.tsx`**
  - Remove individual fee rows
  - Add consolidated "Fees" row with `ButtonIcon`
  - Calculate `totalFees = providerFee + metamaskFee`
  - Move rewards row to last position (after Total)
  - Update text colors (white for Est. points label)
  - Add `onFeesInfoPress` callback prop

#### New Files

- **`PredictFeeBreakdownSheet.tsx`**
  - Bottom sheet component for fee breakdown
  - Displays provider and MetaMask fees separately
  - Uses `shouldNavigateBack={false}` to prevent parent modal closure
  - Accepts `onClose` callback

- **`PredictFeeBreakdownSheet/index.ts`**
  - Export file for new component

#### Localization

- **`locales/languages/en.json`**
  ```json
  {
    "predict.fee_summary.fees": "Fees",
    "predict.fee_summary.provider_fee_label": "Polymarket fee",
    "predict.fee_summary.estimated_points": "Est. points",
    "predict.fee_summary.points_tooltip": "Points",
"predict.fee_summary.points_tooltip_content_1": "Points are how you earn
MetaMask Rewards for completing transactions, like when you swap,
bridge, or predict.",
"predict.fee_summary.points_tooltip_content_2": "Keep in mind this value
is an estimate and will be finalized once the transaction is complete.
Points can take up to 1 hour to be confirmed in your Rewards balance."
  }
  ```

### Tests

#### New Tests (22 total)

- **`PredictFeeSummary.test.tsx`** (12 tests)
  - Consolidated fees display and calculation
  - Fees info icon callback handling
  - Rewards row conditional rendering
  - Rewards row positioning
  - Edge cases (zero fees, missing callbacks)

- **`PredictFeeBreakdownSheet.test.tsx`** (10 tests - New file)
  - Bottom sheet rendering
  - Fee display (Polymarket and MetaMask)
  - `shouldNavigateBack` behavior
  - Close callback handling
  - Ref methods exposure

- **`PredictBuyPreview.test.tsx`** (10 new tests)
  - Rewards calculation formula
  - Rewards point rounding
  - Feature flag conditional display
  - Fee breakdown sheet visibility
  - Loading state propagation

#### Updated Tests (1)

- Fixed existing test to expect "Fees" instead of "Provider fee"

**Total Test Results**: 2,038 tests passing ✅

## Rewards Calculation Logic

```typescript
// Formula: 1 point per cent spent on MetaMask fee
const estimatedPoints = useMemo(
  () => Math.round(metamaskFee * 100),
  [metamaskFee],
);

// Display conditions
const shouldShowRewards = rewardsEnabled && currentValue > 0;
```

### Examples:
- MetaMask fee: $0.50 → **50 points**
- MetaMask fee: $1.23 → **123 points**
- MetaMask fee: $0.00 → **0 points**

## Component Reusability

This implementation reuses existing components:
- ✅ `RewardsAnimations` (from Bridge/Swap)
- ✅ `KeyValueRow` (component library)
- ✅ `ButtonIcon` (design system)
- ✅ `BottomSheet` (design system)
- ✅ Design system tokens (`TextColor`, `IconColor`)

## Feature Flags

- **Rewards display**: Controlled by `selectRewardsEnabledFlag`
- **Fee breakdown**: Always available

## Testing Checklist

- [x] Unit tests for all new components
- [x] Unit tests for modified components
- [x] All existing tests passing (2,038 tests)
- [x] No linter errors
- [x] Tests follow AAA pattern
- [x] Tests follow project guidelines (no "should" in names)
- [x] Edge cases covered (zero values, missing callbacks, etc.)

## Manual Testing

### Test Scenarios

1. **Rewards Display**
   - [ ] Verify Est. points row appears when rewards enabled
   - [ ] Verify points calculation: fee * 100 rounded
   - [ ] Verify Est. points row does NOT appear when rewards disabled
   - [ ] Verify Est. points row does NOT appear when amount is 0

2. **Fee Consolidation**
   - [ ] Verify single "Fees" row shows sum of provider + MetaMask fees
   - [ ] Verify info icon appears next to "Fees" label
   - [ ] Verify tapping info icon opens bottom sheet
   - [ ] Verify bottom sheet shows individual fee breakdown

3. **Bottom Sheet Behavior**
- [ ] Verify bottom sheet displays "Polymarket fee" and "MetaMask fee"
   - [ ] Verify closing bottom sheet does NOT close parent modal
   - [ ] Verify bottom sheet closes on swipe down
   - [ ] Verify bottom sheet closes on backdrop tap

4. **Visual/Styling**
   - [ ] Verify Est. points text is white
   - [ ] Verify all info icons are gray
   - [ ] Verify row order: Fees → Total → Est. points
   - [ ] Verify layout on different screen sizes

## Before/After

### Before
```
Provider fee     $0.10
MetaMask fee     $0.04
Total            $10.14
```

### After
```
Fees [i]         $0.14    ← Tappable info icon
Total            $10.14
Est. points [i]  14       ← New rewards row (white text)
```

### Fee Breakdown Sheet (when tapping [i])
```
╔════════════════════════╗
║ Fees                   ║
╠════════════════════════╣
║ Polymarket fee  $0.10  ║
║ MetaMask fee    $0.04  ║
╚════════════════════════╝
```

## Commit History

1. `feat: Add rewards row to Predict Buy confirmation screen` - Initial
rewards implementation
2. `refactor: Consolidate fee rows and add breakdown sheet` - Fee
consolidation
3. `refactor: Move Est. points row to end and use white text` - Final
positioning and styling
4. `test: Add comprehensive tests for rewards and fee breakdown
features` - Complete test coverage

## Related Issues/PRs

- Related to rewards feature integration
- Consistent with Swap/Bridge rewards display patterns

## Checklist

- [x] Code follows project coding guidelines
- [x] Code follows React Native UI development guidelines
- [x] Used design system components
(`@metamask/design-system-react-native`)
- [x] Used Tailwind CSS with `useTailwind()` hook
- [x] No StyleSheet.create() used
- [x] Proper TypeScript types (no `any`)
- [x] Comprehensive unit tests added
- [x] All tests passing
- [x] No linter errors
- [x] Localization strings added
- [x] Feature flag integrated
- [x] Component reusability maintained
- [x] Follows AAA test pattern
- [x] No breaking changes


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds rewards point estimation and consolidates fee display with a
tappable fees breakdown sheet in Predict Buy.
> 
> - **Predict UI**:
> - `PredictFeeSummary`: Replace separate fee rows with a single "Fees"
row (info icon), display total fees, and add "Est. points" row using
`RewardsAnimations`.
> - `PredictBuyPreview`: Compute `estimatedPoints =
Math.round(metamaskFee * 100)`, gate rewards by
`selectRewardsEnabledFlag`, and open fee breakdown via
`onFeesInfoPress`; pass rewards/fees props.
> - **New Component**:
> - `PredictFeeBreakdownSheet`: Bottom sheet showing per-fee breakdown
(`Polymarket fee`, `MetaMask fee`), `shouldNavigateBack=false`,
`onClose` support.
> - **Localization**:
> - Add strings for `predict.fee_summary.fees`, `provider_fee_label`,
`estimated_points`, points tooltips/error content.
> - **Tests**:
> - Add tests for `PredictFeeBreakdownSheet` and rewards/fees behavior;
update existing expectations from "Provider fee" to "Fees".
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
01962c5. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Adds the Tron network to swaps/bridge.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: added Tron network support in swaps

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Adds Tron support to swaps and bridge, filters non‑tradable Tron
tokens, updates fee/status handling, defaults, and dependencies.
> 
> - **Bridge/Swaps Integration**
> - Allow `TrxScope.Mainnet` in swaps (`isSwapsAllowed`) and bridge
(`ALLOWED_BRIDGE_CHAIN_IDS`, network name map).
> - Add Tron default swap token (`USDT` TRC20) in
`default-swap-dest-tokens.ts` and BIP44 pairs.
> - **Token Handling**
> - New `isTradableToken` utility to exclude Tron resource tokens
(`Energy`, `Bandwidth`, `Max Bandwidth`).
> - `useTokens` now filters non‑tradable tokens, normalizes non‑EVM
addresses, and improves deduping/exclusions.
> - **UI/Logic**
> - `TransactionDetails`: safer multichain fee sum (handles partially
fungible fees) and unified status selection.
>   - Asset utils: mark Solana/Tron assets as swaps‑allowed.
> - **Tests**
> - Extensive tests for non‑EVM normalization, Tron token filtering,
deduplication, and edge cases.
> - **Dependencies**
> - Bump `@metamask/bridge-controller` and
`@metamask/bridge-status-controller` to `^60.1.0`;
`@metamask/tron-wallet-snap` to `^1.7.x` (lockfile updated).
> - **Docs**
>   - Minor README fixes (overlay usage, sample E2E notes).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b88a55b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: GeorgeGkas <georgegkas@gmail.com>
…#22173)

## **Description**

Removed `Text` component wrappers from `BottomSheetHeader` children
across the codebase to ensure consistency with the new API pattern where
`BottomSheetHeader` handles text styling internally.

This refactoring removes redundant `Text` components that were wrapping
string content inside `BottomSheetHeader`. The `BottomSheetHeader`
component now handles the text styling directly, ensuring a consistent
appearance across all bottom sheet headers in the app.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Part of: https://consensyssoftware.atlassian.net/browse/MDP-343

## **Manual testing steps**

```gherkin
Feature: Bottom Sheet Headers Display Correctly

  Scenario: user views various bottom sheets with headers
    Given the app is running
    
    When user opens any bottom sheet modal with a header (e.g., network selector, payment method selector, region selector, account permissions, etc.)
    Then the header text should display correctly with proper styling
    And the header should be visually consistent with other bottom sheet headers
```

## **Screenshots/Recordings**

### **Before**

N/A - Internal refactoring, no visual changes. We can trust the
component to handle styling correctly.

### **After**

N/A - Internal refactoring, no visual changes. We can trust the
component to handle styling correctly.

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---

### **Changes Summary**

**11 component files updated:**
- NetworkSettings/index.js (4 instances)
- NetworkListBottomSheet.tsx
- TooltipModal/index.tsx
- AccountPermissionsConfirmRevokeAll.tsx
- NetworkSelector/NetworkSelector.tsx
- RpcSelectionModal/RpcSelectionModal.tsx
- NetworkManager/index.tsx
- PermittedNetworksInfoSheet.tsx
- ConnectionDetails/ConnectionDetails.tsx
- RegionSelectorModal/RegionSelectorModal.tsx
- PaymentMethodSelectorModal.tsx

**5 test snapshots updated:**
- RegionSelectorModal (8 snapshots)
- PaymentMethodSelectorModal (1 snapshot)
- AccountPermissionsConfirmRevokeAll (1 snapshot)
- ConnectionDetails (1 snapshot)
- PermittedNetworksInfoSheet (1 snapshot)

**Total:** 16 files changed, 54 insertions(+), 60 deletions(-)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Refactors BottomSheetHeader to take raw string children across
modals/selectors and updates tests/snapshots and small header style
expectations.
> 
> - **UI/BottomSheetHeader refactor**:
> - Replace `<Text>` wrappers with raw string children in
`BottomSheetHeader` across:
> - Bridge: `BlockaidModal`, `BridgeNetworkSelectorBase`,
`BridgeTokenSelectorBase`, `QuoteExpiredModal`, `SlippageModal`,
`TransactionDetails/BlockExplorersModal`.
> - Ramp (Deposit): `PaymentMethodSelectorModal`, `RegionSelectorModal`.
> - Account Permissions: `AccountPermissionsConfirmRevokeAll`,
`ConnectionDetails`, `PermittedNetworksInfoSheet`.
> - Networks: `NetworkManager`, `AddAsset/NetworkListBottomSheet`,
`NetworkSelector`.
>     - Misc: `TooltipModal`.
> - **Tests/Snapshots**:
> - Update snapshots to new header structure: add
`testID="header-title"`, center text, and expect fontSize 16.
> - Adjust NetworkManager tests to assert `testID="header"` instead of
mocked header ID; extend icon mocks.
> - **Styles**:
> - Remove unused `heading` style in `NetworkSettings` styles; align
header typography via `BottomSheetHeader`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
ddcd7e7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
metamaskbot and others added 4 commits November 25, 2025 23:07
…mask pay deposits (#23309)

- fix: cp-7.60.0 remove max button from metamask pay deposits (#23287)

## **Description**

Replace the `Max` button in the Predict and Perps deposit confirmations
with a `90%` button.

Remove the target amount from the insufficient fees alert.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: #23265 

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

<img width="300" alt="90"

src="https://github.com/user-attachments/assets/23ce05c6-cd03-4052-b5e5-eae1d9115106"
/>

<img width="300" alt="Alert"

src="https://github.com/user-attachments/assets/87c0f5da-2550-4b4d-98e9-bccda557c195"
/>

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Default deposit quick-action changes from Max to 90% (with optional
hasMax to restore Max), and insufficient fees alerts no longer include a
target amount; tests and wiring updated.
> 
> - **Deposits UI**:
> - `DepositKeyboard`: Replace `Max` with `90%` in default
`PERCENTAGE_BUTTONS`; add `hasMax` prop to swap `90%` for `Max`; memoize
`buttons`.
> - `CustomAmountInfo`/`PredictWithdrawInfo`: Plumb `hasMax`; enable
`hasMax` for Predict Withdraw.
> - **Alerts**:
> - `useInsufficientPayTokenBalanceAlert`: Remove target-amount
calculation/fiat formatting; fees alert always uses
`alert_system.insufficient_pay_token_balance_fees_no_target.message`.
> - **Tests**:
>   - Update `deposit-keyboard` tests for `hasMax` and `90%` behavior.
> - Simplify alert hook tests to expect no-target fees message and
remove obsolete cases.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
fa4a813. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[2b25287](2b25287)

Co-authored-by: Matthew Walsh <matthew.walsh@consensys.net>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

add mon currency to the currencies list

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution? -->

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: add mon currency to currencies list

Fixes:

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

<!-- [screenshots/recordings] -->

<img width="457" height="900" alt="Screenshot 2025-11-25 at 18 47 45"
src="https://github.com/user-attachments/assets/64f9d752-da8b-44ea-978b-5ec8989c14c6"
/>

<!-- [screenshots/recordings] -->

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Lower-cases account keys when storing token balances and adds 'mon' to
supported currencies.
> 
> - **Balances**:
> - Normalize `account` to lower-case in
`dist/TokenBalancesController.(cjs|mjs)` when reading/writing
`d.tokenBalances`, preventing mixed-case keys.
> - **Prices**:
> - Add `"mon"` to `SUPPORTED_CURRENCIES` in
`dist/token-prices-service/codefi-v2.cjs`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3dba1e3. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->



<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

Co-authored-by: Salim TOUBAL <salim.toubal@outlook.com>
…issue (#23307)

- chore: fix signature verification sorting issue cp-7.60.0 (#23220)

## **Related issues**

Fixes: #23222
- issue where URL canonicalization was not properly sorting due to the
way that `.sort` works on React Native.
- add case for `sig_params` being empty, so that we can still sign links
without any parameters that need to be signed
- removed edge case unit test since it added very little value (no one
should be using spaces in a signed URL)

## **Description**

**Reason for change:**
Deep link signature verification was failing for marketing links (e.g.,
`https://link.metamask.io/perps?sig_params=...&utm_...`). The Mobile
app's `canonicalize` function had diverged from the Extension's
implementation, causing signature mismatches.

The root cause: **React Native's `URLSearchParams.sort()` is not
implemented** — it throws an error. This meant parameters weren't being
sorted correctly, so the canonical URL didn't match what was signed.

**Improvement/solution:**
Updated the `canonicalize` function to:

1. **Use custom array sorting** instead of `URLSearchParams.sort()`
(which is broken in React Native)
2. **Handle empty `sig_params` explicitly** — when `sig_params=''`, only
include `sig_params` itself in the canonical URL (allows appending UTMs
after signing)
3. **Use `getAll()`/`append()`** instead of `get()`/`set()` to preserve
multiple values for the same parameter (matches Extension behavior)
4. **Use `encodeURIComponent()`** for consistent URL encoding

These changes align Mobile with the Extension's canonicalization logic,
ensuring signed deep links verify correctly.

## **Changelog**

CHANGELOG entry: Fixed deep link signature verification failing for
marketing links with UTM parameters

## **Manual testing steps**

```gherkin
Feature: Deep Link Signature Verification

  Scenario: user opens a signed deep link with sig_params and appended UTMs
    Given a signed deep link with sig_params listing specific parameters
    And UTM parameters are appended after signing

    When user opens the deep link in the app
    Then the signature verifies successfully
    And the user is not shown the unsigned link warning modal

  Scenario: user opens a signed deep link with empty sig_params
    Given a signed deep link with sig_params= (empty)
    And UTM parameters are appended after signing

    When user opens the deep link in the app
    Then the signature verifies successfully
    And only sig_params is used for verification (UTMs ignored)

  Scenario: user opens a signed deep link without sig_params (legacy)
    Given a signed deep link without any sig_params parameter

    When user opens the deep link in the app
    Then all parameters (except sig) are included in verification
    And the signature verifies successfully (backward compatibility)
```

## **Screenshots/Recordings**

### **Before**

Signed marketing links showed the "unsigned link" warning modal due to
signature verification failure.

### **After**

Signed marketing links verify correctly and open without the warning
modal.

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

---

**Labels to add:** `team-mobile-platform`
[65ae4f9](65ae4f9)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Revamps deep-link canonicalization to use custom param sorting,
explicitly handle empty `sig_params`, and preserve multi-value params;
updates tests accordingly.
> 
> - **Deeplink verification utils
(`app/core/DeeplinkManager/ParseManager/utils/verifySignature.ts`)**:
>   - **Canonicalization**:
> - Replace `URLSearchParams.sort()` with custom key sorting and
explicit encoding via `encodeURIComponent`.
> - Handle `sig_params=''` by signing only `sig_params` itself (exclude
other params).
> - When `sig_params` present, include only listed params (via
`getAll`/`append`) and append `sig_params`.
> - Legacy path: without `sig_params`, include all params except `sig`.
> - **Tests (`verifySignature.test.ts`)**:
> - Add cases for deterministic alphabetical sorting and empty
`sig_params` behavior.
> - Expand coverage for multi-param/missing-param scenarios and legacy
behavior.
>   - Remove low-value edge case test for spaces in `sig_params`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
310f03d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Kylan Hurt <6249205+smilingkylan@users.noreply.github.com>
runway-github bot and others added 2 commits November 26, 2025 12:32
… explorer urls on bridge txs (#23311)

- fix: cp-7.60.0 Generate correct blockchain explorer urls on bridge txs
(#23273)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Fix an issue where the blockchain explorer urls were not generated
successfully when bridging assets.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Generate correct blockchain explorer URLs when bridging
assets

## **Related issues**

Fixes: #23171

## **Manual testing steps**

```gherkin
Ensure that the correct blockchain URLs are generated when visiting the transaction
details screen after bridging/swapping assets. 

Also ensure that the correct URLs are also generated for old bridge/swaps transactions (no regressions).
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Fixes bridge transaction explorer URL generation across EVM and
non‑EVM chains with proper fallbacks and updates tests accordingly.
> 
> - **Bridge Hook (`useMultichainBlockExplorerTxUrl`)**:
> - Switches to `useBlockExplorer` from `app/components/hooks` and uses
`getEvmBlockExplorerUrl` to derive EVM explorer base URLs.
> - Falls back to `getEtherscanBaseUrl` and builds links via
`@metamask/etherscan-link` when custom explorer is unavailable.
> - Determines explorer names via URL for non‑EVM and via
`blockExplorer.getBlockExplorerName` for EVM.
> - Keeps network image sourcing and chain name resolution, handling
unknown networks gracefully.
> - **Hook Tests** (`useMultichainBlockExplorerTxUrl.test.tsx`):
> - Comprehensive coverage for parameter validation, EVM (mainnet,
Optimism, Polygon) and non‑EVM (Solana) paths, fallbacks, explorer name
resolution, network image sourcing, and edge cases.
> - **Modal Test** (`BlockExplorersModal.test.tsx`):
> - Updates expectations to one `Etherscan` and one `Optimistic` button.
> - **Block Explorer Hook** (`useBlockExplorer.ts`):
>   - Exposes `getEvmBlockExplorerUrl` in returned API.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
4b8a441. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[f93f627](f93f627)

Co-authored-by: George Gkasdrogkas <georgegkas@gmail.com>
runway-github bot and others added 2 commits November 26, 2025 15:35
…23286)

- fix: cp-7.60.0 predict withdraw using gas station (#23255)

## **Description**

Fix Predict withdraw when using gas station with insufficient existing
token balance.

Bump `transaction-controller` and `transaction-pay-controller`.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: #23137 #23126

## **Manual testing steps**

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [x] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Skips adding gas-fee-token batch/7702 external sign when
`txMeta.isGasFeeTokenIgnoredIfBalance` is true, adds tests, exposes
remote feature flag to messengers, and bumps transaction-related
dependencies.
> 
> - **Confirmations**:
> - Respect `txMeta.isGasFeeTokenIgnoredIfBalance` in
`useTransactionConfirm` to avoid adding `batchTransactions` or setting
`isExternalSign`.
> - Add tests ensuring no `batchTransactions`/`isExternalSign` when gas
fee token should be ignored.
> - **Engine/Messaging**:
> - Delegate `RemoteFeatureFlagController:getState` to transaction
controller messengers.
>   - Minor typing adjustment around `getNetworkClientRegistry`.
> - **Dependencies**:
> - Bump `@metamask/transaction-controller` to `62.3.0` and
`@metamask/transaction-pay-controller` to `10.1.0` (with related
lockfile updates).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8f80ad1. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[69d1ae2](69d1ae2)

---------

Co-authored-by: Matthew Walsh <matthew.walsh@consensys.net>
Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com>
…`:accountCreated` idempotency) cp-7.60.0 (#23326)

- chore: bump `eth-snap-keyring` (to enable `:accountCreated`
idempotency) cp-7.60.0 (#23310)

## **Description**

Bumping `@metamask/eth-snap-keyring` to enable `notify:accountCreated`
idempotency which is required by the Bitcoin Snap.

This will reduce the number of "misaligned" warnings we had with
Bitcoin.

Similar to:
- MetaMask/metamask-extension#38292

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes:
- #23324

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

### **Before**

### **After**

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Bumps `@metamask/eth-snap-keyring` to 18.0.2 and updates related
keyring dependencies for alignment.
> 
> - **Dependencies**:
> - Bump `@metamask/eth-snap-keyring` to `^18.0.2` in `package.json` and
`yarn.lock`.
> - Align related keyring packages in `yarn.lock`:
`@metamask/keyring-api` `^21.2.0`, `@metamask/keyring-internal-api`
`^9.1.1`, `@metamask/keyring-internal-snap-client` `^8.0.1`,
`@metamask/keyring-snap-client` `^8.1.1`, `@metamask/keyring-snap-sdk`
`^7.1.1` (including peer dep updates).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b4dd0a7. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[97fe703](97fe703)

Co-authored-by: Charly Chevalier <charlyy.chevalier@gmail.com>
runway-github bot and others added 4 commits November 26, 2025 20:06
…hains cp-7.60.0 (#23334)

- fix: update logic to support all non-evm chains cp-7.60.0 (#23328)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

Update logic to include all non-evm chains when parsing deep link urls.

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: Update logic for deeplink parsing to take into account
all non-EVM chains

## **Related issues**

Fixes: #23314 

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ x ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ x ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ x ] I’ve applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Generalizes asset metadata fetching to support all non-EVM chains by
replacing Solana-specific logic with `isNonEvmChainId`.
> 
> - **Bridge asset metadata utils
(`app/components/UI/Bridge/hooks/useAssetMetadata/utils.ts`)**:
> - Generalizes non-EVM handling in `fetchAssetMetadata` by replacing
Solana-specific check with `isNonEvmChainId`.
> - Imports `isNonEvmChainId` from `@metamask/bridge-controller` and
updates non-EVM address extraction via `parseCaipAssetType`.
> - Maintains existing EVM path (using `parseCaipChainId`,
`formatAddressToCaipReference`, `formatChainIdToHex`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
8bc891b. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[3cf4f74](3cf4f74)

Co-authored-by: SteP-n-s <stylianos.panagakos@consensys.net>
…istered error detection in BasicInfo form (#23333)

- fix(ramp): cp-7.60.0 fix phone already registered error detection in
BasicInfo form (#23299)

## **Description**

Fixed error handling in BasicInfo component to correctly access error
codes from Axios error responses. The code was previously trying to
access `error.error.errorCode` but Axios errors have the structure
`error.response.data.error.errorCode`, which prevented error code 2020
(phone already registered) from being detected correctly.

## **Changelog**

CHANGELOG entry: null

## **Related issues**

Fixes: #23302

## **Manual testing steps**

```gherkin
Feature: BasicInfo form error handling

  Scenario: user submits form with already registered phone number
    Given I am on the BasicInfo screen with valid form data
    When I submit the form with a phone number that is already registered
    Then I should see an error message indicating the phone is already registered
    And I should see a "Log in with email" button
    And clicking the logout button should navigate to the email entry screen
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<img width="333" height="720" alt="image"

src="https://github.com/user-attachments/assets/0a01a7be-e4bb-496c-8396-e77d5785b668"
/>


### **After**



https://github.com/user-attachments/assets/e8acba92-1032-4f49-a5bd-84a605bda71f

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Fixes BasicInfo to read Transak error code 2020 from Axios responses,
show a formatted email message with a logout action, and navigate to
email entry; tests updated to use AxiosError.
> 
> - **BasicInfo (`BasicInfo.tsx`)**:
> - Parse Axios error via `response.data.error` to detect Transak
`errorCode` `2020`.
> - Extract email from error message and display localized "phone
already registered" text.
> - Toggle `isPhoneRegisteredError` to render a "Log in with email"
action; on press, call `logoutFromProvider(false)` and navigate to
`Routes.DEPOSIT.ENTER_EMAIL`.
> - Preserve error visibility and log on logout failure; minor import of
`AxiosError`.
> - **Tests (`BasicInfo.test.tsx`)**:
> - Update error mocks to use `AxiosError` with
`response.data.error.errorCode` `2020`.
> - Assert formatted message, presence/absence of logout button, logout
flow navigation, and graceful handling of logout errors.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
46aa1dd. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[3807955](3807955)

Co-authored-by: Amitabh Aggarwal <aggarwal.amitabh@gmail.com>
…23331)

- fix: cp-7.60.0 non-evm accounts not found (#23318)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

Fix Non-EVM accounts not found 
Fixes part of this
MetaMask/metamask-extension#38104

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry: fix: non-evm accounts not found

## **Related issues**

Fixes: MetaMask/metamask-extension#38104

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Upgrade snaps dependencies in package.json:
@metamask/solana-wallet-snap to ^2.5.0 and @metamask/tron-wallet-snap to
^1.13.0 (with lockfile updates).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
b108def. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[ec74886](ec74886)

Co-authored-by: Alejandro Garcia Anglada <aganglada@gmail.com>
Co-authored-by: João Loureiro <175489935+joaoloureirop@users.noreply.github.com>
<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

Allows machines with small amount of logical cpu core count
to run Metro worker code concurrently

For example, previous value would force GH runners to run worker code
in the main Metro process.
This was causing Metro bundler processes to crash due to JS heap
memory limit being exhausted

## **Changelog**

<!--
If this PR is not End-User-Facing and should not show up in the
CHANGELOG, you can choose to either:
1. Write `CHANGELOG entry: null`
2. Label with `no-changelog`

If this PR is End-User-Facing, please write a short User-Facing
description in the past tense like:
`CHANGELOG entry: Added a new tab for users to see their NFTs`
`CHANGELOG entry: Fixed a bug that was causing some NFTs to flicker`

(This helps the Release Engineer do their job more quickly and
accurately)
-->

CHANGELOG entry:

## **Related issues**

Fixes:

## **Manual testing steps**

```gherkin
Feature: my feature name

  Scenario: user [verb for user action]
    Given [describe expected initial app state]

    When user [verb for user action]
    Then [describe expected outcome]
```

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**

<!-- [screenshots/recordings] -->

### **After**

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
@sonarqubecloud
Copy link

@joaoloureirop
Copy link
Contributor

@SocketSecurity ignore npm/@metamask/transaction-pay-controller@10.1.0

…#23375)

- fix: fix recipient account icons cp-7.60.0 (#23362)

## **Description**

The icon being used for each recipient addresses was not re-using their
account group icons (we use the EVM address of a multichain account
group as the seed of account's icons).

This PR fixes this while keeping the original `recipient.address` as a
fallback (which should never happen anyway).

## **Changelog**

CHANGELOG entry: Fix account's icons for send flows

## **Related issues**

Fixes:
- #22806

## **Manual testing steps**

```gherkin
Feature: Send non-EVM token

  Scenario: user starts a send flow for Solana
    Given the user has funds

    When user selects the recipient address
    Then he should see the same icons than the one used for the account list
```

## **Screenshots/Recordings**

### **Before**



https://github.com/user-attachments/assets/100969c2-15e9-49c4-a2f3-cd24aac8e839

<img width="382" height="192" alt="Screenshot 2025-11-27 at 13 28 36"

src="https://github.com/user-attachments/assets/53225dd9-8e47-4788-850e-09579c312e96"
/>
<img width="377" height="250" alt="Screenshot 2025-11-27 at 13 28 22"

src="https://github.com/user-attachments/assets/07e5b9aa-4a1c-44ff-ac6a-402a0712bd1a"
/>

### **After**



https://github.com/user-attachments/assets/221c05e4-b040-4583-b81f-de674f716db1

<img width="385" height="220" alt="Screenshot 2025-11-27 at 13 29 52"

src="https://github.com/user-attachments/assets/02b959f4-7334-454f-8939-931054f68bf3"
/>
<img width="383" height="194" alt="Screenshot 2025-11-27 at 13 29 36"

src="https://github.com/user-attachments/assets/a1eb109d-e74a-4de2-9844-ec5675e565c3"
/>

## **Pre-merge author checklist**

- [ ] I’ve followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding

Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [ ] I've completed the PR template to the best of my ability
- [ ] I’ve included tests if applicable
- [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [ ] I’ve applied the right labels on the PR (see [labeling

guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Recipient avatars now use the account group’s icon seed with address
fallback; useAccounts adds accountGroupId and tests updated accordingly.
> 
> - **Confirmations UI**:
> -
`app/components/Views/confirmations/components/UI/recipient/recipient.tsx`
> - Avatar `accountAddress` now sourced from account group seed via
`selectIconSeedAddressByAccountGroupId(recipient.accountGroupId)` with
fallback to `recipient.address`.
>     - Adds Redux selector usage and `AccountGroupId` typing.
> - **Send Hooks**:
>   - `app/components/Views/confirmations/hooks/send/useAccounts.ts`
>     - Includes `accountGroupId` in returned recipient objects.
> - **Tests**:
> - `useAccounts.test.ts` expectations updated to include
`accountGroupId` across EVM, Solana, Bitcoin, and Tron cases.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
f41df4d. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->


[0f7ac87](0f7ac87)

Co-authored-by: Charly Chevalier <charlyy.chevalier@gmail.com>
@github-actions
Copy link
Contributor

🔍 Smart E2E Test Selection

  • Selected E2E tags: SmokeWalletPlatform, SmokeAccounts, SmokeAssets, SmokeConfirmationsRedesigned, SmokeTrade, SmokeCard
  • Risk Level: medium
  • AI Confidence: 75%
click to see 🤖 AI reasoning details

Analysis Summary

I've analyzed 100 changed files across the codebase. The changes span multiple areas with varying levels of criticality:

Major Change Categories:

  1. Bridge Components (~30 files in app/components/UI/Bridge/):

    • Components: TransactionDetails, BlockExplorersModal, QuoteDetailsCard, TokenSelectorBase, BridgeView
    • Hooks: useTokens, useTokenSearch, useBridgeQuoteRequest, useMultichainBlockExplorerTxUrl, useGasIncluded
    • Utils: isTradableToken
    • Impacts: Asset search, token selection, bridge transactions, quotes
    • This affects SmokeTrade and SmokeAssets tags
  2. Card Features (~8 files in app/components/UI/Card/):

    • Views: CardAuthentication, CardHome, CardWelcome
    • Significant UI and authentication flow changes
    • Impacts: SmokeCard tag
  3. Multichain Accounts (~6 files in component-library/components-temp/MultichainAccounts/):

    • AccountCell, AccountListHeader, MultichainAccountSelectorList
    • Account selection and display components
    • Impacts: SmokeAccounts and SmokeWalletPlatform tags
  4. Asset Search & Management (~8 files):

    • AssetSearch component changes
    • useSearchRequest and useTrendingRequest hooks
    • AssetOverview utilities
    • Impacts: SmokeAssets tag
  5. Navigation & Core UI (~5 files):

    • MainNavigator changes
    • App.tsx navigation updates
    • BottomSheetHeader, ListItemSelect components
    • AccountFromToInfoCard, AccountInfoCard
    • Impacts: SmokeWalletPlatform, SmokeConfirmationsRedesigned
  6. Test Infrastructure & CI/CD:

    • GitHub workflow files (run-e2e-smoke-tests-*.yml)
    • E2E smart selection scripts
    • Configuration files (.detoxrc.js, .eslintrc.js)
    • No direct test execution needed, but affects test framework
  7. Dependencies & Patches:

    • @metamask-assets-controllers patch (TokenBalancesController changes for account address case handling)
    • expo-updates, rive-react-native patches
    • android/app/build.gradle
    • Potential impacts across multiple areas

Risk Assessment:

Medium Risk because:

  • Many UI components changed across critical flows (Bridge, Card, Accounts)
  • Asset-related functionality changes could affect token display and transactions
  • Navigation and account management changes are fundamental but appear targeted
  • No changes to core Engine/Controllers (would be high risk)
  • Changes appear to be feature additions/improvements rather than core rewrites
  • Test infrastructure changes don't affect app functionality directly

Tag Selection Rationale:

  1. SmokeWalletPlatform - Navigation and core wallet UI changes (MainNavigator, App.tsx)
  2. SmokeAccounts - Multichain account components and account management UI
  3. SmokeAssets - Asset search, display, and management changes
  4. SmokeConfirmationsRedesigned - AccountFromToInfoCard and confirmation flow UI components
  5. SmokeTrade - Extensive Bridge component changes affecting token swaps and bridge transactions
  6. SmokeCard - Card authentication and home screen changes

Not Selected:

  • SmokeCore - No core wallet functionality or critical controller changes
  • SmokeIdentity - No identity/authentication system changes (Card auth is feature-specific)
  • SmokeNetworkAbstractions/SmokeNetworkExpansion - No network layer changes visible
  • SmokeSwaps - Bridge changes are more general; SmokeTrade covers swap functionality
  • SmokeStake/SmokeNotifications/SmokeRewards/SmokePerps/SmokeRamps/SmokePredictions - No changes in these areas
  • SmokeMultiChainPermissions/SmokeMultiChainAPI/SmokeAnalytics - No changes in these specific areas

Confidence: 75%

Moderate-high confidence based on:

  • Clear view of changed files and their purposes
  • Could not get git diffs for all files (some returned "Could not get git diff")
  • Many changes are in UI/UX layers rather than core logic
  • Test/snapshot updates suggest feature refinements
  • The volume of changes (100 files) suggests this is a significant release
  • Dependencies patches indicate some underlying fixes that may have broader impact

View GitHub Actions results

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-7.60.0 Issue or pull request that will be included in release 7.60.0 size-XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.